私のコンピュータをローカルサーバーにバックアップするためのbashスクリプトを書いています。アーカイブを圧縮する必要がありますが、内部sshコマンドでif条件がどのように機能するかを見つけることができません。
if [ ssh [email protected] '$(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"' ]
then
ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
&& rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
fi
「引数が多すぎます」(if内で)エラーが発生します。
私は何が間違っていましたか?
答え1
構成を簡素化し、コードを読む次の人に何が起こっているのかを理解する機会を提供することをお勧めします。主な問題は、間接実行$( ... )
と[ ... ]
テスト演算子を混同しているようです。流れを間違って理解したら謝ります。しかし、意図したことは次のとおりです。
# Count files on the remote system and confirm that there is at least one
DATE7=$(date -v -7d '+%Y%m%d')
NFILES=$(ssh [email protected] "ls -d '/snapshots/$DATE7'* 2> /dev/null | wc -l")
# If the ssh worked and we have found files then archive them
if [ $? -eq 0 && 0 -lt $NFILES ]
then
# Archive the files
ssh [email protected] "
tar -czf '$ARCHIVES_DIR/$YESTERDAY.tar.gz' '$SNAPSHOT_DIR/$YESTERDAY'* &&
rm -rf '$SNAPSHOT_DIR/$YESTERDAY'
"
fi
これはARCHIVES_DIR
、SNAPSHOT_DIR
およびYESTERDAY
スクリプトの他の場所でローカルに定義されていると仮定します。
"..."
変数の値はすぐに挿入されますが、'...'
テキストは$WIDGET
ドル記号で始まるリテラル7文字の文字列として扱われます。このコードには、" '...' "
などのシーケンスがあることを考慮すると、これは注目に値します。' "..." '
答え2
コマンドの戻り状態をif条件として使用できますが、正しい構文は括弧なしです。一方、リモートホストでは角かっこまたは「test」コマンドを使用する必要があります。 (私はこれをテストすることを好みます。)これを試してください:
if ssh [email protected] 'test $(ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l) != "0"'
then
ssh [email protected] "tar -czf $ARCHIVES_DIR/$YESTERDAY.tar.gz $SNAPSHOT_DIR/$YESTERDAY* \
&& rm -rf $SNAPSHOT_DIR/$YESTERDAY*"
fi
dateコマンドを確認したい場合があります。少なくとも私のLinuxシステムではdate: invalid option -- 'v'
。
答え3
この形式if [ ... ]
はの呼び出しですtest
。括弧で囲まれた式は、構文規則に従って評価され解釈されるtest
戻りコードがエクスポートされます。if
括弧だけを削除したい場合があります。
if ssh ... | grep -q .
このコマンドは、一致が成功した場合に成功したgrep
戻りコード(「true」)を返します。if
この場合、ssh コマンドの出力が空でない場合です。元のコードをもう少し文字通り翻訳すると、次のようになります。
if [ $(ssh ... | wc -l) != 0 ]
実行時に$(...)
、式は埋め込みコマンド出力のテキストに置き換えられます。つまり、test
対応する整数とゼロの間の正しい比較が表示されます。
答え4
あなたの質問は条件式にのみ関係しているので、if部分だけをテストしました。
次のことができます。
if [ $(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l') != "0" ]
then
# do something
fi
私の答えにいくつかの追加:
行数がゼロでないことを確認する代わりに、SSH接続を確立できないことを考慮する必要があるかもしれません。
接続が失敗すると、結果も「0ではない」になるからです。
より良いエラー処理のために、次のものを使用できます。
lines=$(ssh [email protected] 'ls -d /snapshots/$(date -v -7d +%Y%m%d)* 2> /dev/null | wc -l')
result=$?
# If 'ssh'-command succesful:
if [ $result == "0" ]
then
# If number of lines is non-zero:
if [ $lines != "0" ]
then
# do something
fi
else
# handle error based on $result
fi