2012-02-24 10 views
3

私はawkを使用して特定のプロセスのpidを名前で取得しています。ベース名またはawkのendswith?

$ ps 
    PID TTY   TIME CMD 
1858 ttys000 0:00.15 -bash 
4148 ttys000 0:01.37 /a/b/c/foo 

しかしCMD列の処理が正確にfoo(なし絶対パス)であれば、私のシェルスクリプトのみ動作します:OSX上ps出力のようなものである

#!/bin/sh 

for pid in $(ps | awk '$4 == "foo" { print $1 }') 
do 
    i=1 
    echo "killing foo at pid $pid" 
    kill $pid && echo 'ok' || echo 'failed' 
done 

私はbasenameを使用することができます考えていますが、どのように私はawkからそれを呼び出すのですか?
または
$4.endswith('foo')のようなものがawkにありますか?条件については

答えて

6

awkは正規表現を使用できます。正規表現は、//の間にある

awk '$4 ~ /\/foo$/ { print $1 }' 

:だからむしろ$4 == "foo"よりも、あなたのような何かを行うことができます。 \/foo$は「バックスラッシュの後にfooが続き、次にフィールドの終わり」と言います。この場合、フィールドは/a/b/c/fooなので、一致します。

+0

ありがとう!私は精神でupvote :) – user46874

2

、あなたはに変換され

$4 ~ /\/foo$/ 

を使用することができ、「第四のフィールドと一致する行の末尾に 『foo』で続くスラッシュを(エスケープ)。」

+0

ありがとうございます!大いに感謝します – user46874

2

正規表現に加えて、文字列操作をsubstr($4, length($4) - 2) == "foo"として使用できます。

+0

ああ、知っておきたい。ありがとう。 – user46874

2

あなたがどのようにについて、名「foo」を持っているすべてのプロセスを殺すためにしようとしているようだ:すべての

killall foo 
+0

+1:新しいコマンドは私が存在していたかわからなかった。私のMacに「pkill」スクリプトを書いたのは、それがなかったからです。これまでの 'killall'コマンドについて知りたがっています。 Macに相当する 'pgrep'はありますか? –

+0

@Hai Vu、とても素敵です。私はこの命令を知らなかった。それは静かな殺害のためにはうまくいくが、私は冗長な殺害も必要とする。ありがとう。 – user46874

+0

@ user46874:** killall -v **は冗長なkillを行います。 –

3

まず、あなたが代わりにforwhile read構文を使用する必要があります。 forループでは、$(...)のコマンドがforループを開始する前に実行するまで待つ必要があります。さらに、コマンドバッファをオーバーランさせる可能性があります。あなたの問題をどうするくらい

ps | awk '$4 == "foo" { print $1 }' | while read pid 
do 
    i=1 
    echo "killing foo at pid $pid" 
    kill $pid && echo 'ok' || echo 'failed' 
done 

何を、私は私の胸をそのオフを取得する必要があります:あなたはそれに遭遇していないときに大きな問題今日、しかし、あなたは何かが間違っていたという兆候を得ることは決してないだろう。

あなたの答えに今の

awkは自動的にループを行いますので、あなたはとにかくawkを使用していることから、なぜそれがあなたのために仕事をさせませんか?ほとんどのawkの実装にはsystemコマンドが含まれているため、awkスクリプト内でkillを実行することができます。

また、man psを見て、PSオプションを確認してください。ほとんどのpsコマンドは-oオプションを使用して、印刷するフィールドを指定することができます。私のpsコマンド(ちょうどOS X上にある)は、ucommを使用できます。これは、ディレクトリやコマンドラインパラメータのないコマンドの名前です。あなたの状況に役立ちます。 PID、およびコマンド名のsansディレクトリとコマンドラインパラメータ::私はpsコマンドのための2つの列のみ印刷されるps -opid, ucommを使用します

$ ps -o pid,ucomm 
    PID UCOMM 
    1 launchd   
    10 kextd   
    11 UserEventAgent 
    12 mDNSResponder 
    13 opendirectoryd 
    14 notifyd   
    15 fseventsd  
    16 configd   
    17 diskarbitrationd 
    18 syslogd   

を(ちょうど1つの警告、ucommがで物事をカットするように見えます14列目または16列目にあります)。

awkについては、-vパラメータを使用してAwk変数を定義できます。これは、シェルスクリプトを作成し、awkがコマンドのパラメータからプログラムの名前を取得したい場合に便利です。

あなたが知っているように、$ 1はPIDを表し、$ 2はディレクトリまたはコマンドラインパラメータを表すコマンドを表します。

foopsコマンドのすべての行をフィルタリングするのに、$2 == commandを使用できます。これはifステートメントへのショートカットです。

そして、awkのほとんどの実装では、あなたのawkスクリプト内からkillのようなコマンドを実行するために使用することができますsystem機能を持っています。我々は我々が必要とするほとんどすべてを持っているように見える:

素敵なきれいな1つのライナーだが、それは、システムのコマンドのステータスをチェックしません、またそれが失敗したときにそれが出エコーないか、何のコマンドとPIDあなた
ps -o pid,ucomm | awk -v command="foo" '$2 == command {system("kill " $1)}' 

再殺し。

Awkは単なるコマンドではありません。それはまた、不安定なプログラミング言語です。 systemコマンドの返答をテストし、いくつかのprintステートメントを追加することができます。私はこれをテストしていないが、それはかなり近いはずである。

ps -o pid,ucomm | awk -v command="foo" '$2 == command { 
    print "Killing " $2 " at PID " $1 
    if (system("kill " $1)) { 
     print "Failed to kill PID " $1 
    } 
}' 

ifではなくif (! system("kill " $1)) {する必要があります。

+0

Perl! Perlのオリジナルの設計目標は、awk、sed、grep、findなどの多くの複雑な特殊目的言語のための単一の汎用的な置き換えとして機能することでした。bashのようなシェルスクリプト言語は、しかし、彼らはawkとsedを使用する傾向があります。 Perlの代わりにPythonやRubyが好きな人もいます。私はUnixとLinuxのシステム管理のためにPythonを読んできましたが、Perlを本当に置き換えることができるかどうかはわかりません。 – minopret

+0

@minopret - 私はPerl開発者ですが、Perlはこれを行うことができます。しかし、Perlはタグにはなかったので、私はこのような場合にPerlソリューションを使用しないようにしています。しかも、それはAwkでやるだけでも簡単です。 OS Xにはこれらの2つのコマンドが付属していないので、私はPerlで書かれた私のMacに 'pgrep'と' pkill'タスクを持っています。 –

+0

@David W.、洞察に感謝します。非常に便利! – user46874

0

pidを探すときは、awkプロセスを除外する必要があります。そうしないと、代わりに検索プロセスが終了する可能性があります。

kill $(ps -aef | awk -v program="mplayer" '$0 ~ program {if ($0 !~ "awk") print $2}') 
関連する問題