我有以下Z shell脚本来启动一个程序实例,如果一个程序尚未主动运行,即使有一个僵尸实例,或者恢复已停止的实例。我觉得必须有一个更好的方法来使用,也许使用perl。 shell脚本看起来太尴尬了 - 至少应该可以使用其他语言进行文本操作,比如perl或awk。
launchprogram(){
if [ $# = 0 ]
then
cat <<\EOF
launchprogram requires at least one argument.
Usage: launchprogram <program> <optional arguments>
EOF
return 1
fi
mystatus=Z # assume we have a zombie process
process="$(pgrep "$1" | tr \\n ,)"
echo "$process"
process="${process%,}"
if [ "$process" != '' ]
then
process="$(ps -o 'pid s cmd' -p "$process" | sed '1 d')"
fi
oldifs="$IFS"
IFS="$(printf \nX)"
IFS="${IFS%X}"
for i in $process
do
mystatus="${process[2]}"
case $mystatus in
(T)
if ! kill -CONT "${i[1]}"
then
IFS="$oldifs"
return $?
fi
;;
(Z)
;;
(*)
IFS="$oldifs"
return $?
;;
esac
done
IFS="$oldifs"
setopt nobgnice
"$@" >/dev/null 2>&1 &!
unsetopt nobgnice
}
答案 0 :(得分:2)
我看不出你应该用awk / perl / ...替换什么,但这个脚本似乎不起作用:
n
,而预期的IFS只包含换行符。"$process[2]"
不正确,因为它是第二个字符,而不是第二个字符。没有提到它是$i[2]
的意思。${i[1]}
相同。for i in $process
将始终迭代一个值:整个$process
。因此,我会使用以下注意事项重写脚本:
pgrep
支持ps
,因此不需要-C
(这假定程序名称不包含空格或逗号)。由于有办法删除标题,因此不需要sed
。${(f)}
。 ${(s. .)}
用于按空格分割。cmd
)列未在任何地方使用。mystatus
不需要默认值,因为它不会在循环之外的任何地方使用。launchprogram(){ emulate -L zsh if [ $# = 0 ] then cat EOF return 1 fi local mystatus local process local i local -a iarr process="$(ps -o 'pid=,s=' -C "$1")" echo "$process" for i in ${(f)process} do iarr=( ${(s. .)i} ) mystatus="${iarr[2]}" case $mystatus in (T) if ! kill -CONT "${iarr[1]}" then return $? fi ;; (Z) ;; (*) return $? ;; esac done setopt nobgnice "$@" >/dev/null 2>&1 &! # With emulate -L unsetting option is not needed }