web-dev-qa-db-ja.com

ファイルがsshとifステートメントでリモートサーバーにチェックインするかどうかをテストする方法

$SSHPATH/$ID.*内のファイルが存在するかどうかをテストしようとしています。 sshpassを使用してパスワードを入力しているので、入力する必要はありません。

ファイルが存在しない場合にコードを実行したい

if [ "sshpass -p $SSHPASS ssh root@$SSHHOST test ! -f $SSHPATH/$ID.*" ]; then

これは、ファイルがリモートサーバーに存在する場合でもtrueを返すようです。どうして?

コマンドが成功または失敗した場合に条件付きで何かを行う方法 の重複だとは思わないこれも機能しないため、ファイルが存在しない場合は実行されませんでした

if sshpass -p "$SSHPASS" ssh "root@$SSHHOST" test ! -f "$SSHPATH/$ID.*"; then
2
Freedo

pLumoが説明したように 、テストは常に成功します。

やりたいことは、パターン$SSHPATH/$ID.*が何かに展開するかどうかをテストすることです。これは、パターンが複数の名前に拡張される可能性があり、-fテストは単一のパス名にのみ適用できるため、-fを使用したテストとは異なります。

ローカルでは、これを行うことができます

set -- "$SSHPATH/$ID".*
if [ -e "$1" ]; then ...; fi

これにより、定位置パラメーター($1$2など)がsetに指定されたパターンに一致する名前に設定されます。次に、ifステートメントは、最初の一致が既存の名前であるかどうかをテストします(パターンが何にも一致しなかった場合、パターンはほとんどのシェルで展開されないままになります)。

これをsshで実行するには:

ssh user@Host "set -- '$SSHPATH/$ID'.*; [ -e \"\$1\" ]"

不自然な引用により、$SSHPATHが展開されている間、$IDおよび"$1"localシェルによって展開されます。リモートで。

これにより、パターンが既存の名前に一致した場合は終了ステータスがゼロ(「成功」)になり、一致しなかった場合(またはsshが何らかの方法で失敗した場合)はゼロ以外(「失敗」)になります。

これをifステートメントで次のように使用できます。

if ssh user@Host "set -- '$SSHPATH/$ID'.*; [ -e \"\$1\" ]"; then
   # do something for success
else
   # do something for failure
fi

non-存在をテストするには、テストを否定します。

if ssh user@Host "set -- '$SSHPATH/$ID'.*; [ ! -e \"\$1\" ]"; then
   # do something for failure
else
   # do something for success
fi

sshpassの使用は無視しましたが、質問で行ったように、sshの前に単に付けてもよいでしょう。

3
Kusalananda

最初のコマンドは同じです

if [ "some string" ]; then ... fi

これは常に真実です。

2番目のコマンドはほぼ正しいですが、!引用符で囲むかエスケープします。それ以外の場合は、シェルによって解釈されます。

パス内の特殊文字の問題を回避するために、コマンド全体を二重引用符で囲み、パスを単一引用符で囲みます。 *単一引用符の外:

if sshpass -p "$SSHPASS" ssh root@$SSHHOST "test ! -f '$SSHPATH/$ID.'*"; then ... fi

パターンが複数のファイルに一致する場合、 テストは失敗します

1
pLumo