web-dev-qa-db-ja.com

bash内のAWKの問題

こんにちは、長い歴史短い:特定のプロセスを強制終了するためにCIサーバーを介して実行するスクリプトを作成しようとしています。

インターネットで検索すると、次のコマンドが見つかりました。

myuser@server:/home/myuser# ps -ef | grep someUniqueText | grep -v grep | awk '{print $2}'
5263

コンソールで実行すると、必要なもの(5263)が返されるため、このbashを作成しました。

#!/bin/bash

PROCESSNAME=$1
PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | awk '{print $2}');

echo $PID;

次のように実行すると:

myuser@server:/home/myuser# ./killProcess.sh somename
5263 4587 1236

Bashスクリプトは、最初に必要なプロセスである3つの数字を返します。他の2つが何であるかはわかりませんなぜ? o.O

PS .:最初にテストするためにechoを使用していますが、kill -9に変更します

1
Jorge Campos

./killProcess.sh somenameを実行すると、次のようなプロセス

/bin/bash ./killProcess.sh somename

が存在し、ps | grep | grep | awk-行もテキストsomenameを含むため、これを見つけます。なぜ1つだけではなく2つの追加のPIDを取得するのか正確にはわかりませんが、bashkillProcess.shの間に親子関係があると思います。 1行ではPIDがPIDとして表示され、もう1行ではPPIDとして表示されます。

これらのPIDは、スクリプト名に基づいてgrepすることで回避できます。 $0に保存されるため、

PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | grep -v $0 | awk '{print $2}');

または(プログラム呼び出しが少ない場合):

PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $0 | awk '{print $2}');

別の(より安全な)方法は、スクリプトのPIDを削除することです。 $$に保存されます:

PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $$ | awk '{print $2}');

または、awkですべて実行します。

PID=$(ps -ef | awk "/$PROCESSNAME/ && !/awk/ && !/$$/ {print \$2}");

ここでは\$2をエスケープする必要があるため、シェルではなくawkで解釈されます。このコマンドの意味は次のとおりです。

行に$PROCESSNAMEが含まれ、awkが含まれておらず、独自のPIDが含まれていない場合、2番目の列を印刷します。

利点は(理論上)、3 grepsとawkではなく、追加のコマンド(awk)が1つだけ必要なため、これが高速に実行されることです。

だが:

これらすべてgrepsおよびawksは完全ではなく、常にここで考えていない状況を見つけてください(部分一致など)。そのため、すでに作成されているツールのいずれかを使用することをお勧めします。

2
PerlDuck

シェル関数として、psg( "ps | grep")を呼び出す同様のアイデアを実装したことがあります

psg() {
    local -a patterns=()
    (( $# == 0 )) && set -- $USER
    for arg do 
        patterns+=( "-e" "[${arg:0:1}]${arg:1}" )
    done
    ps -ef | grep "${patterns[@]}"
}

これは、パターンの最初の文字を括弧で囲むトリックを使用するため、次のようになります

ps -ef | grep "[s]omename"

これにより、grep -v grepパイプラインの一部。

引数を渡さない場合、ユーザー名を使用してプロセスを検索します。

2
glenn jackman