我這裡有一段漂亮的小程式碼,如果有另一個腳本實例正在運行,它將從腳本中退出:
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
man ps
我在研究並添加@goldilocks 的一些代碼後想到了這個。它在處理帶有空格的參數方面做得很好,如果腳本被調用為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
如果目前正在運行兩個或多個$0
使用相同參數呼叫的進程,則會發生這種情況。
答案4
使用/行程:
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
值中沒有任何空格,因此您可以直接比較它們。如果參數順序發生變化,它不會注意到。