KornShellのAIX 7.1.0で実行されているプロセスを確認する正確で信頼性の高い方法

KornShellのAIX 7.1.0で実行されているプロセスを確認する正確で信頼性の高い方法

私は何かが実行されている間にスクリプトの他のインスタンスがないことを確認したいので、スクリプトが実行されているかどうかを確認する方法を見つけようとしました。これまで私は次のことを試しました。

#! /bin/ksh93

getProcessNum(){
    processNum=$(ps -ef | grep -E "$1" \
        | grep -vE "emacs|vi |ve |grep|ps|tail|tee|runProcess|jlast|tlast|elast" \
        | awk '/'$USER'/ { if($1 == "'$USER'") print $0}' \
        | awk -v myPid=$$ '{if ($3 != myPid) print $0}' \
        | wc -l
    )
}

getProcessNum "myAvoidedScript.k"

if [[ $processNum -gt 1 ]]; then
    echo "There are $processNum instances running. Stopping..."
else
    echo "You can continue"
fi

わかりました:

ThisProcessID=4063450
myUser  4063450  5636606   0 19:06:48 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  8978492  5964234   0 19:06:48 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  3277270  9109712 113 11:07:58  pts/5 70:50 /bin/ksh93 myAvoidedScript.k

この方法で十分だと思いますが、一部のプロセスは同じスクリプトの一部でも計算されます。このスクリプトを実行しようとすると、何も実行されませんが、1より大きい数値が返されることを確認しました。

それで、私は非常に正確な時間に始まる重複した項目を削除しようとすれば十分であると言いました。私は次のように試しました。

#! /bin/ksh93

getProcessNum(){
    processNum=$(ps -ef | grep -E "$1" \
        | grep -vE "emacs|vi |ve |grep|ps|tail|tee|runProcess|jlast|tlast|elast" \
        | awk '/'$USER'/ { if($1 == "'$USER'") print $0}' \
        | awk -v myPid=$$ '{if ($3 != myPid) print $0}' \
        | sort -k 4 | awk '!x[$5]++' | wc -l
    )
}

getProcessNum "myAvoidedScript.k"
if [[ $processNum -gt 1 ]]; then
    echo "There are $processNum instances running. Stopping..."
else
    echo "You can continue"
fi

時には正しい結果が得られますが、時には次のような結果が得られます。

返されたPIDは、常に現在のPID($$)と同じではありません。

ThisProcessID=4063450
myUser  3177476  5964232   0 19:06:49 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  3277270  9109712 113 11:07:58  pts/5 70:50 /bin/ksh93 myAvoidedScript.k

このスクリプトをほぼ1秒間実行しても、まったく同じスクリプトの2つのインスタンスが表示され続けます。

ThisProcessID=4063450
myUser  4063450  5636606   0 19:07:48 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  5177476  5964232   0 19:07:49 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  3277270  9109712 113 11:07:58  pts/5 70:50 /bin/ksh93 myAvoidedScript.k

このスクリプトを実行するたびに、正しいプロセスのみを安定した方法で実行する方法を知っている人はいますか?

PS。フラグファイルが利用可能であることを知っていますが、これは多くのスクリプトを変更する必要があることを意味します。

答え1

これをテストするAIXシステムはありませんがpspsgrep、awk、wc を単一の awk コマンドに減らすこともできます。例えば、

getProcessNum(){
    procs=$(ps -u "$USER" -f)
    processNum=$(printf '%s\n' "$procs" |
        awk -v myPid="$$" -v name="$1" '
            index($0,"ksh93 " name) != 0 && $2 != myPid {tot++}
            END {print tot}'
    )
}

答え2

このスクリプトを実行するたびに、正しいプロセスのみを安定した方法で実行する方法を知っている人はいますか?

ps現在のユーザーが所有しているプロセスのリストを要求し、-u $USERそのプロセスのpid、親pid、および完全なコマンド文字列(コマンドと引数)を印刷し、追加のチェックのためにそれをawkに渡すことができます。 Awkは現在のスクリプトのpid(-v me=$1)と検索プロセスの名前(-v procname=$2)を提供し、次に3つの要件を満たす行を検索するように指示されます。

  1. ここで pid(列 1) は次のようになります。いいえ現在のスクリプトのpid
  2. ここで、ppid(列2)は次のようになります。いいえ現在のスクリプトのpid
  3. ここで、コマンド文字列は指定されたパラメータと一致します。

行がこれらの両方の要件を満たしている場合、awkはpidを印刷してからそのpid(存在する場合)をパイプしてwc -lインスタンスを計算します。単にカウンターを増やすこともできますが、他の目的でPIDを調べたい場合は、それを検索する方法が提供されます。

getProcessNum() {
  ps -u "$USER" -o pid=,ppid=,args= |
  awk -v me="$1" -v procname="$2" \
    '$1 != me && $2 != me && index(substr($0,19,length(procname)), procname) { print $1 }' |
  wc -l
}

これとの最大の違いははい現在のスクリプトのすべての子プロセスを具体的に無視できるように、親プロセスpidを印刷するように要求しますps。他の違いは、決定するときに次のようなindex偽の肯定を最大限に防ぐためにこれを行うことです。もちろん人工的だvi ksh93 myAvoidedScript.k

ps -o argsこれらのインスタンスが正しく除外されるようにするには、スクリプトの正確な注文(指定どおり)を渡す必要があります。ここのようにgetProcessNum $$ "/bin/ksh93 myAvoidedScript.k"。引数(/bin/ksh93 myAvoidedScrip.k foo)、オプション(ksh93 -x myAvoidedScript.k)、またはフルパス(/bin/ksh93 /path/to/myAvoidedScript.k)を使用するか、別のインタプリタパス(./ksh93 myAvoidedScript.k)または直接()を使用してスクリプトを呼び出すことができる場合、./myAvoidedScript.kこのチェックは失敗します。

正確なスクリプト呼び出しを保証できない場合は、一度に1つのスクリプトコピーしか実行されないことを保証するのは困難です。

関連情報