2017-12-05 16 views
0

私が使用bashのコマンドで異なる結果が得られます。
1.

$ ssh [email protected] ps -aux|grep -v \"grep\"|grep "/srv/adih/server/app.js"|awk '{print $2}' 
6373 

2.

$ ssh [email protected] echo $(ps -aux|grep -v \"grep\"|grep "/srv/adih/server/app.js"|awk '{print $2}') 
8630 

最初の結果が正しいものであると私はそれを実行エコー時間を変更します。しかし、なぜ彼らが違うのか分かりません。


私は何をしていますか?
ワークステーションのリソースは非常に限られているため、リモートマシンを使用してノードアプリケーションを実行します。デバッグモードでssh [email protected] "cd/applocation & & grunt serve"を使って実行します。私がCTRL+Cというコマンドを実行すると、gruntタスクは停止しますが、アプリケーションはまだデバッグモードで実行されています。私はちょうどそれを殺したいと思うし、私は最初にpidを取得する必要があります。

答えて

3

sshが実行される前に、ローカルシェルによってコマンド置換が実行されます。

ローカルシステムの名前はhereで、リモートでthereある

ssh there echo $(uname -n) # should have proper quoting, too 

がローカルuname -nを実行し、その後にthereに拡張コマンドラインecho hereを送信するのに対し、

ssh there uname -n 

thereを印刷する場合は実行される。

さらに、は、出力前にワイルドカード展開と空白トークン化を実行する必要がある場合を除いてuseless use of echoです。これを印刷する前にcommandに出力してください。

また、grep x | awk { y }useless use of grepです。それはおそらくawk '/x/ { y }'にリファクタリングする必要がありますが、もちろん、ここではpidofを再利用しているだけです。

ssh [email protected] pidof /srv/adih/server/app.js 

ローカルに印刷されたPIDをキャプチャしたい場合にのみ、それを殺すために必要がある場合は、そのための構文は、もちろん

pid=$(ssh [email protected] pidof /srv/adih/server/app.js) 

あり、それは

ssh [email protected] pkill /srv/adih/server/app.js 
+0

'pidof'と' pgrep'と 'pkill'の実装にはプラットフォームの違いがあります。一致したプロセスの完全な引数リストを調べるには '-f'を渡す必要があります。 – tripleee

2

短い答えます:$(ps ...)コマンド置換がローカルコンピュータで実行されているし、その出力が(echoコマンドと共に)リモートコンピュータに送信されます。基本的にはssh [email protected] echo 8630です。

あなたの最初のコマンドはおそらくあなたが期待したことをしていないでしょう。パイプはローカルコンピュータ上で解釈されるので、ssh [email protected] ps -auxが実行され、ローカルコンピュータの出力がgrepにパイプされ、ローカルコンピュータの別のgrepにパイプされます。そのすべてを実行したいと思っています結果をリモートコンピュータ上で使用してプロセスを強制終了することができます。

長い答え:物事はシェルで解析されて実行されますが、少し混乱します。ミックスでsshコマンドを使用すると、状況はさらに複雑になります。基本的には、ローカルシェルが別のコマンド(パイプで区切られた、;など)に分割し、$(command)$variable(単一引用符で囲まれていない限り)を展開するなど、コマンドラインを解析します。その後、引用符とエスケープを取り除き(ジョブを実行した)、さまざまなコマンド(たとえばssh)に引数として結果を渡します。 sshはその引数をとり、リモートコマンドの部分のように見えるものすべてをそれらの間にスペースを入れてスティックし、リモートコンピュータのシェルに送信します。このプロセスは再びになります。

これは、ローカルシェルではなくリモートシェルで解析/動作させたい場合は、$|のような引用やエスケープが必要であることを意味します。引用符は入れ子になっていないので、全体を引用符で囲むことは期待通りに機能しない可能性があります(たとえば、注意しないとawkコマンドの$2がローカルコンピュータで展開される可能性があります一重引用符で囲みます)。

このように物事が乱雑になった場合、sshコマンドの引数ではなく、リモートコマンドをhere-documentとして渡すのが最も簡単な方法です。しかし、さまざまな$の拡張がローカルシェルによって行われないようにするために、ここのドキュメント区切り文字の前後に引用符が必要です。

ssh [email protected] <<'EOF' 
echo $(ps -aux|grep -v "grep"|grep "/srv/adih/server/app.js"|awk '{print $2}') 
EOF 

注:テキストがリモートコンピュータにそのまま送信されるため、リモートコマンドのインデントには注意してください。タブ文字で字下げした場合は、<<-をここの文書区切り文字(例:<<-'EOF')として使用して先頭のタブを削除します。

EDIT:@ 3人が指摘したように、awkはジョブ全体を行うことができるので、grepは複数の必要はありません。パターン内の "/"文字をエスケープする必要があるため、検索コマンドを検索結果から除外する必要はありません。

ps -aux | awk '/\/srv\/adih\/server\/app.js/ {print $2}' 

ここでは、実際の目標はkillの関連するPIDであると仮定しており、echoはテスト用です。その場合は、実際のコマンドは、ビーイングを巻き取る:

ssh [email protected] <<'EOF' 
kill $(ps -aux | awk '/\/srv\/adih\/server\/app.js/ {print $2}') 
EOF 

それは正しくありません場合は、全体echo $()事は完全に最高のスキップされます。パイプラインの出力をキャプチャする理由はなく、echoです。それを実行して直接出力させます。

pkill(または類似のもの)が利用可能な場合は、代わりにそれを使用する方がはるかに簡単です。

+1

あなたは、OPのコードで大きな醜い無駄使いを修正しませんでした。あなたは本当に 'ssh [email protected] <<<" ps -aux | awk '/\/srv\/adih\/server\/app\.js/ {print \ $ 2}' "(ここにリファクタリングされていますコメント内でコードを動作させるための文字列)。 – tripleee

+0

何かがあなたの言ったとおりではありません。私が最初のコマンドで得た結果は、まさにリモートマシン上のPIDです。 –

+0

$ ssh [email protected] ps -aux | grep -v \ "grep \" | grep "/srv/adih/server/app.js"|awk '{print $ 2}' ** 6373 ** と私はリモートコンピュータでそれを実行しました:$ ps aux | grep "/srv/adih/server/app.js" git ** 6373 ** 0.0 0.4 1650012 37164 pts/1 Sl + 13:40 0:00/usr/local/bin/node --debug/srv/adih/server/app.js git 9224 0.0 0.0 118488 2204 pts/2 S + 14:33 0:00 grep --color = auto /srv/adih/server/app.js –

関連する問題