SSHセッションでパイプを使用した読み取りが失敗するのはなぜですか?

SSHセッションでパイプを使用した読み取りが失敗するのはなぜですか?

findで見つけたフォルダの代わりに空白行が表示されるのはなぜですか?

ssh -o stricthostkeychecking=no -o userknownhostsfile=/dev/null \
  -o batchmode=yes -o passwordauthentication=no [email protected] \
  "sudo find /folder/CFGKCP/KCS\ Pro/Job\ Setup -name JOBCFG.info \
    | while read linea; do echo $linea; done";

答え1

Romeoが指摘したように、コマンドの周りに二重引用符を使用します。これは、コマンドを実行する前に変数が拡張されることを意味しますssh。したがって、whileループの本文は次のようになります。

echo $linea

以前は存在しなかった可能性があるため、渡されssh lineaたコマンドは空の文字列にecho置き換えられます。linea

コマンドパラメータの周りに一重引用符を使用すると、パラメータ拡張が発生せず、文字列がそのまま渡されるので問題ありません。

ssh -o stricthostkeychecking=no -o userknownhostsfile=/dev/null -o batchmode=yes -o passwordauthentication=no [email protected] 'sudo find /folder/CFGKCP/KCS\ Pro/Job\ Setup -name JOBCFG.info | while read linea; do echo $linea; done'

あるいは、エスケープすると$シェルが拡張しないように指示します。

答え2

二重引用符を使用しているからです。これは、$linea実行前に拡張されたことを意味します。ssh以下を使用してこれをテストできますset -x

$ set -x
$ ssh user@host "find /var  | while read line; do echo $line; done"
+ ssh user@host 'find /var  | while read line; do echo ; done'

ご覧のとおり、実際に実行されるコマンドにはecho変数はありません。これを防ぐには、二重引用符の代わりに一重引用符を使用できます。

ssh user@host 'find /var  | while read line; do echo "$line"; done'

またはローカルでwhileループを実行します。

ssh user@host find /var  | while read line; do echo "$line"; done

上記の例では、コマンドの出力に従ってfindリモートホストで実行され、ローカルで実行されます。whilessh

答え3

ループを避けてくださいwhile read

ssh [email protected] '
  sudo find "/folder/CFGKCP/KCS Pro/Job Setup" -name JOBCFG.info -exec sed -i "
    /^\[General]/,/^\[/ {
      s/^JobRoot = .*/JobRoot = C:\\\\LOTES\\\\TMP\\\\\r/
    }" {} +'

または一重引用符を使用してください。

ssh [email protected] '
  sudo find "/folder/CFGKCP/KCS Pro/Job Setup" -name JOBCFG.info -exec sed -i '\''
    /^\[General]/,/^\[/ {
      s/^JobRoot = .*/JobRoot = C:\\LOTES\\TMP\\\r/
    }'\'' {} +'

(これは\rすでにGNUに固有のものであるため、これを使用することもできます-i。)

答え4

変数を引用符で拡張する方法について説明していただきありがとうございます。これで問題が始まる場所を理解しました。エコーの代わりに順序を使用するため、入れ子になった単一引用符を使用する必要があります。より詳細な例は次のとおりです。

ssh [email protected] '
    sudo find /folder/CFGKCP/KCS\ Pro/Job\ Setup -name JOBCFG.info|
        while read line; do
            sudo sed '/^\[General\]/,/^\[/ {s/^JobRoot = .*/JobRoot = C:\\LOTES\\TMP\\\r/}' "$line" |sudo tee "$line".modificado; sudo mv -f "$line".modificado "$line";
        done
';

関連情報