ssh - 複雑なリモートコマンドの実行

ssh - 複雑なリモートコマンドの実行

次のことをしたいシェルコマンド離れて機械:

/bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out

retailこのコマンドは、基本的にいくつかの砂糖が追加された一般的なLinuxであるバイナリを使用します。tail詳細については、以下を確認してください。これgithubリポジトリ。

シェルに上記のコマンドを入力すると、リモートコンピュータからそれは私が望むこと自体を行うので、書かれたコマンドは機能的な観点から正確です。それは私が望むことをします。

問題は私が欲しいものです。実装するこのコマンドはスクリプトから私のラップトップにリモートシステムを起動します。

これは何ですか?頑張ったしかし、すべてのコマンドは目的の出力を印刷せずにログ行を印刷しない完全に:

ssh [email protected] /bin/retail -f -u "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out

[それから脱出を試みるか、代わりに]使用しようとしましたが、おそらくすべての組み合わせを使用しましたが、すべて'"役に立たない

これ希望の出力例:Normalのように動作し、tail新しい行が文字列の指定された行と一致すると終了します。同様に、リモートコンピュータで実行すると、次のように動作します。

私は自分に尋ねました:おそらくretailSSHを介して実行することはできませんか?私は普通のUNIXを使ってtailみました。効果があるSSH経由。作家はretailそうです。POSIX互換tail彼のシステムをそれに置き換えることができます。だからこれもそうだと思います。大丈夫です。バイナリファイル自体。

したがって、質問は次のようになります。sshコマンドを正しくインポートするようにコマンドのパラメータ形式をどのように指定しますか?


コメントへの返信ジャッケン551:

以下を意味する場合:

ssh [email protected] '/bin/retail -f -u "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out'

そしてはい、試してみました。印刷もできますログ行なしそして、入力プロンプトに戻りません。


正解に対する反応ジェラルド・フィレ:

残念ながら同じ行動。ログを印刷せず、入力プロンプトを返しません。完全性のために、以下を試しました。

ssh [email protected] /bin/retail -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out

正解に対する反応パトリック:

残念ながら否定的です。完全性を期すために提案された両方のソリューションを試しました。ここ最初:

CMD="$(printf "%q " /bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
ssh [email protected] "$CMD"

結果:ログを印刷せず、入力プロンプトを返しません。

しかも第二:

ssh -T [email protected] <<'EOF'
/bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF

結果:擬似端末を出力しますが、ログではありませんそして実際にいいえ帰る入力プロンプト:

 Pseudo-terminal will not be allocated because stdin is not a terminal.
Linux my-remote-server 4.1.15-1-lts #1 SMP Tue Dec 15 20:54:13 CET 2015 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

私が以来試験を終えた今やるべきいくつかの解決策があります。sh スクリプト呼び出し、次のretailコマンドが含まれています。ジェラルド・フィレ提案。まだ欲しい良い一行可能であれば(該当する行を含むスクリプトを作成する必要はありません)。


回答アーチャーマール答え:

元のコマンドを使用して指定し、-tここにaを追加しましたが、結果は次のようになります。

ssh -t [email protected] /bin/retail -f -u "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out

そして効率的な。 Archemar あなたはあなたの記事を書く必要があります回答でコメントするだから確認してみることができます。

答え1

時々、コマンドは端末を処理しますが、これは問題ではないため、端末を割り当てることも$PATHできます。sshtty

~によるとman ssh

-t 疑似端末割り当てを強制します。これは、リモートコンピュータ上で任意の画面ベースのプログラムを実行するために使用することができ、これは、例えばメニューサービスを実装する場合に有用である。複数の -t オプションは、ssh にローカル tty がない場合でも tty 割り当てを強制します。

ただ使用

ssh -t sshuser@host ...

答え2

Jaken551の提案は実用的なソリューションに近いですが、追加レベルのネストされた参照のために若干異なります。まず、何が起こっているのか見てみましょう。

echo私の一般的な技術は、コマンドの前にaを付けることです(完璧ではありませんが、通常は十分です)。

# Your original command which you say works locally
$ echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

# The command though ssh
$ ssh example.com echo "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out
INFORMATION [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler [ajp-nio-8009] /opt/tomcat/logs/catalina.out

# The command through ssh with the quotes
$ ssh example.com 'echo "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out'
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \["ajp-nio-8009"\] /opt/tomcat/logs/catalina.out

したがって、出力の違いに注意してください。これら2つのsshバージョンではエスケープが異なります。

最初の例で何が起こるのかは、最初のsshレベルの参照がローカルシェルによって削除され、複数のssh引数(echo、、INFORMATION \[main\] ...)を受け取り、一緒にリンクされて単一の引数を形成し、echo INFORMATION \[main\] ...ローカルシェルのシェルで評価されることです。リモートエンドはsh -c 'echo INFORMATION \[main\] ...'

2番目のssh例では、最初のレベルの参照はローカルシェルによって再び削除されるため、sshはそれを受信して​​からecho "INFORMATION \[main\] ..."リモート側で評価しますsh -c 'echo "INFORMATION \[main\] ..."'。それでもう少し良くなりましたが、まだ引用符とエスケープを削除して2つのシェルレイヤーを処理する必要があります。

 

この問題を解決する方法は2つあります。最初の方法は、STDINからコマンドを渡すことです。これにより、コマンドが実際に実行されたときにシェルで一度だけ処理されます。

ssh -T example.com <<'EOF'
echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

ただし、これはリモートコマンドがTTYまたはSTDINにアクセスできないことを意味するため、コマンドにSTDINが必要な場合は機能しません。

2番目の方法は、シェルに追加の見積もりレベルを追加させることです。

$ CMD="$(printf "%q " echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
$ ssh example.com "$CMD"
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

(仲介者は必要ありません$CMD。インラインで実行できますssh ... "$(printf "%q " ...)"。読みやすくするために別々に行いました。)

 

重要な要約:次のいずれかの方法が適している可能性があります。

ssh -T [email protected] <<'EOF'
/bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF

CMD="$(printf "%q " /bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
ssh [email protected] "$CMD"

答え3

目的のタスクを実行する別のシステムでスクリプトを作成し、パラメータなしでそのスクリプトを呼び出すと、操作がはるかに簡単になります。別の方法は、受け取った引数を表示するスクリプトを反対側に作成することです(例:echo_args.sh)。

#!/bin/ksh

echo "$0 $@"
ARG=1
while [ $# -gt 0 ]
do
  echo "$ARG: $1"
  shift
  (( ARG++ ))
done

その後、次のように電話できます。

ssh [email protected] bin/echo_args.sh  -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out

あなたは以下を得ます:

bin/echo_args.sh -f -u INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out
1: -f
2: -u
3: INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]
4: /opt/tomcat/logs/catalina.out

これは、パラメータが反対側の端に正しく到達したことを示します。これで、echo_args.shを小売プログラムに置き換えることができます。

ssh [email protected] /bin/retail -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out

関連情報