よくミスるのでメモです。
手動手順を自動実行するスクリプトのエラーを確実に検出する点で、ソフトウェアテストの小ネタの仲間に入れて下さい。。。(思想的には共通部分があるはず、、)
ホスト環境に開発環境構築する場合などを想定
sudo apt-get update
時にパスワードを聞かれないようにする(参考)
sudoersを更新することで可能
$ sudo visudo # 以下の行に追加する
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD:ALL
上記だと、セキュリティ的に良くないことも多いと思うので、username
を指定する場合は以下
username ALL=NOPASSWD: ALL
もしくは、sudo -S
でパスワードをパイプで受け取る
echo 'passwd' | sudo -S apt-get update
対話処理は先に実行しておく
例えばOpenCVビルド時は対話処理が必要なので先に実行しておく
sudo apt-get update -y
sudo apt-get install -y gdm3 ## 対話ウィンドウが出たら --> OK --> gdm3 を選択
cd ~
git clone https://github.com/mdegans/nano_build_opencv
cd nano_build_opencv
./build_opencv.sh 3.4.10
yes/no
が聞かれる場合にy/n
を自動入力
yes``no
コマンドを使う
yes | ./build_opencv.sh 3.4.10
yes
はずっとy
を出力する
$ yes
y
y
y
...
エラー発生時はエラー終了させる
1部だけエラーになっても素通りすると後から分かりづらいので、エラー側に倒す
trap``set -E
を使うと便利
# エラーが起こったら異常終了させる
set -E
function failure(){
echo "error end!!"
exit 1
}
# エラー発生時にコールする関数を設定
trap failure ERR
|
を使ってパイプで結果を渡す途中のエラーも検知する場合は、set -eo pipefail
を設定すると便利
#!/bin/bash
set -eo pipefail
sl | ls
echo "don't show this comment"
部分的にエラー処理したい場合は、$?
で結果を判断しても良いかもしれないです。
ls test.txt
RESULT=$? # no such file or firectoryのとき1がはいる
if [ $RESULT -ne 0 ];then
echo "no file"
fi
エラー関数がある場合は、||
で結果を渡しても良いかもしれないです。
function func_error(){
echo "error"
}
ls test.txt || func_error # no such file or firectoryのときfunc_errorが実行される
前処理でrm -r
する場合はエラーにならないようにする
rm -rf
だと、指定したdirectoryがない時にエラーにならない
$ sudo rm -rf directory_name
$ echo $?
0
rm -r
だと、指定したdirectoryがない時にエラーになる
$ sudo rm -r directory_name
rm: directory_name: No such file or directory
$ echo $?
1
$HOME/.bashrc
にリダイレクトする場合
$HOME/.bashrc
読み込み時に実行したいコマンドがある場合は'シングルクオーテーション'
で囲む
echo 'eval `dbus-launch --sh-syntax`' >> $HOME/.bashrc
逆に、$HOME/.bashrc
へのリダイレクト時に実行したいコマンドがある場合は"ダブルクオーテーション"
で囲む
echo "echo `date`" >> $HOME/.bashrc
'シングルクオーテーション'
の場合は文字列のまま、"ダブルクオーテーション"
の場合はコマンドが実行された結果が展開される。
$ echo 'echo `date`'
echo `date`
$ echo "echo `date`"
echo 2020年 11月21日 土曜日 23時22分15秒 JST
ライブラリバージョンチェック
厳密にライブラリバージョンの一致が必要な場合は、チェックをしても良さそう。
# ex. opencv pythonのバージョンを調べる場合
python3 -c "import cv2 ;print(cv2.__version__);"
複数回実行時にエラーにしない
インストール手順アップデートなどにより、、同じスクリプトを複数回実行する場合がある。
この場合に異常側になるべく倒さない方が便利な時もある。
例えば、既にrosをインストールしている場合はスキップ側に倒すなどした方がいい時もある。。
function install_ros(){
# check if already install ros
rosversion -d
ret=$?
if [ $ret -eq 0 ];then
echo "ros already installed, skip install ros"
return 0
fi
# install ros
# ...
}
ただし-e
指定してる場合はエラーになるので、この場合はif
の中に含むとよい
#!/bin/bash
set -e
if [ ! -z `env | grep "ROS_DISTRO"` ];then
echo "ROS_DISTRO found"
else
echo "ROS_DISTRO not found"
fi
環境変数よりコマンド実行結果をみた方が良い場合もある
#!/bin/bash
set -e
if [ ! -z `rosversion -d` ];then
echo "ROS_DISTRO found"
else
echo "ROS_DISTRO not found"
fi
周辺パッケージアップデートの影響をなるべく回避する
開発が活発なライブラリを使う場合は、アップデート時のデグレを引くこともある。
branch指定、もしくは動作確認時点のバージョン指定により回避する。
git clone http://github.com/test/repository
git checkout xxx # branch指定、もしくは動作確認時点のバージョン指定
機械学習ライブラリ系は、特に変化が大きいのでバージョン固定する方がよさそうです。
但し、周辺パッケージの変化に気付き難くなるので一概に解決とは言えない。。
その他
何かより良い方法がありましたらアドバイス頂けると幸いです。