0

我有以下 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
}
4

1 回答 1

2

我看不出你应该用 awk/perl/... 替换什么,但这个脚本似乎不起作用:

  1. 带有 IFS 的两行产生的 IFS 等于n预期的仅包含换行符的 IFS。
  2. "$process[2]"不正确,因为它是第二个字符而不是第二列。更不用说这是$i[2]那个意思了。
  3. ${i[1]}.
  4. 默认情况下,zsh 中的变量不会自动拆分为参数,因此for i in $process将始终迭代一个值:整个$process.

因此,我将使用以下注意事项重写脚本:

  1. pgrep不需要,因为ps支持-C(假设程序名称不包含空格或逗号)。两者都不sed需要,因为有办法删除标题。
  2. zsh${(f)}适合那些需要按行拆分字符串的人。并按${(s. .)}空格分割。
  3. 最后 ( cmd) 列不在任何地方使用。
  4. mystatus不需要默认值,因为它不会在循环之外的任何地方使用。
启动程序(){
    模拟 -L zsh
    如果 [ $# = 0 ]
    然后
        猫  
EOF
        返回 1
    菲
    本地状态
    本地进程
    本地我
    本地 -a iarr
    进程="$(ps -o 'pid=,s=' -C "$1")"
    回声“$进程”
    对于 ${(f)process} 中的 i
    做
        iarr=( ${(s.)i} )
        mystatus="${iarr[2]}"
        案例 $mystatus 在
            (T)
                如果 !杀死 -CONT "${iarr[1]}"
                然后
                    返回$?
                菲
                ;;
            (Z)
                ;;
            (*)
                返回$?
                ;;
        经社理事会
    完毕
    setopt nobgnice
    "$@" >/dev/null 2>&1 &!
    # 使用 emulate -L 不需要取消设置选项
}
于 2013-11-02T22:50:43.807 回答