ここに、別のインスタンスが実行されている場合にスクリプトを終了する、すばらしい小さなコードがあります。
single_instance(){
if pidof -x "${0##*/}" -o %PPID >/dev/null; then
exit 0
fi
}
しかし、私が探しているのは、スクリプトが実行された場合にのみ終了する関数です。同じ引数で呼び出される。
解決策を自分で見つけられることはわかっていますが、、などcat | grep | awk | cut | sed | tac | sort | uniq
のユーティリティを使用してこれを行う簡単な方法があるかどうか疑問に思っていますpidof
。ps
これをどうやって実行しますか?
答え1
次のようなことができます:
#!/bin/bash
single_instance() {
pid=$(pidof -x "${0##*/}" -o %PPID)
if [[ $(xargs -0 < /proc/$pid/cmdline) == $@ ]]
then
echo QUITTING
exit 1
fi
}
single_instance $(xargs -0 < /proc/$$/cmdline)
while :
do
sleep 10
done
答え2
@goldilocks のコードをいくつか勉強して追加した後、これを思いつきましたman ps
。スペースを含む引数を適切に処理し、スクリプトが次のように呼び出された場合にも機能しますbash scriptname
。
single_instance(){
if ps -efww | grep "$(ps -o cmd= -p $$)$" | grep -vq " $$ "; then
exit 0
fi
}
答え3
fn() { IFS='
'; set -- $(ps -o args= -C "${0##*/}")
unset IFS
[ $(($(printf $(printf %s\\n "$@" | sort | uniq -c | sort -rn)))) -gt 1 ] &&
exit 0
}
同じ引数で呼び出されたexit 0
2 つ以上のプロセスが現在実行されている場合に発生します。$0
答え4
使用/proc:
single_instance(){
local tl=$(cat /proc/$$/cmdline)
local l
tl=${tl##*/}
for pid in $(pidof -x "${0##*/}" -o %%PPID); do
l=$(cat /proc/$pid/cmdline)
if [ ${l##*/} = $tl ]; then
echo "already running..."
exit 0
fi
done
}
起動パスなしでコマンドライン間の正確な比較を行います (スクリプトで行ったように)。/proc/*/cmdline
値にはスペースが含まれていないため、直接比較できます。ただし、パラメータの順序が変更されても、認識されません。