Shell 防止POSIX xargs尝试运行空命令

Shell 防止POSIX xargs尝试运行空命令,shell,posix,kill,xargs,Shell,Posix,Kill,Xargs,我对bash不是很在行,但我正在尝试创建一个脚本来杀死一些java进程: /usr/ucb/ps -auxww \ | grep 'XUnit' \ | grep -v 'grep' \ | cut -c -2000 \ | awk '{print $2;}' \ | xargs kill 此处使用的是cut,因为awk可能会因线路过长而失效(请参阅中的LINE\u MAXlimit) 当没有此类进程时会出现问题-xargs尝试在没有参数的情

我对bash不是很在行,但我正在尝试创建一个脚本来杀死一些java进程:

/usr/ucb/ps -auxww    \
  | grep 'XUnit'      \
  | grep -v 'grep'    \
  | cut -c -2000      \
  | awk '{print $2;}' \
  | xargs kill
此处使用的是
cut
,因为
awk
可能会因线路过长而失效(请参阅中的
LINE\u MAX
limit)

当没有此类进程时会出现问题-
xargs
尝试在没有参数的情况下运行
kill
,导致错误


我的xargs不接受
-r
-如果args为空则不运行,正如回答中所建议的那样。

专门解决手头的问题,忽略手头的方法实际上是否是终止进程的适当方法:

xargs sh -c '[ $# -gt 0 ] && exec "$0" "$@"' kill

这种方法让
xargs
启动一个shell,该shell查看其参数列表的长度(如果只传递
kill
,则该长度将为0,因为
-c'script'
后面的参数以
$0
开头,不包括在
$\code>计数中);只有在至少给出一个参数的情况下,该shell才会运行给定的命令。

是通常情况下,有
-r
选项来
xargs
,请参阅:

否则,您可以创建一个bash函数并将其放在xargs之前的管道中:

handle_empty(){
  while read line; do
    if test -z "$line"; then
        echo 'There was an empty line, exiting.' > /dev/stderr
        exit 0;
    fi
    echo "$line"
  done;
}

export -f handle_empty;
并像这样使用它:

docker volume ls -qf dangling=true | handle_empty | xargs docker volume rm 
有关更多信息,请参阅:

这里已经给出了答案:顺便说一句——如果你有
pkill
,你最好在一个命令中使用它,而不是试图通过一个巨大的管道过滤
ps
输出。而且,
awk
可以自己完成
grep
cut
的工作,所以即使你要坚持使用管道,也没有理由让它如此复杂。例如:
ps auxww | awk'(/XUnit/&&!/awk/){print$2}'
。但是,如上所述,最佳实践是根本不使用
ps
。阅读POSIX规范中关于
awk
,允许其符合
LINE_MAX
,通常为2k。刚刚在那里学到了一些新的东西——尽管我很好奇,您正在使用的哪个实现实际上强制了这个限制。@BenjaminW.,是的!我认为非常节省的方法是
ps-e-opid=-oargs=|awk'/[X]Unit/{print$1}'
。如果您担心这个限制,可以在awk之前抛出一个
cut-c-$(getconf LINE\u MAX)
。为什么不在管道中放置一个
handle\u empty
函数呢?如果参数为空,则使用0退出并回显“有一个空行”。。。请参阅:或使用-r选项-
-r
不可移植--正如您链接的答案所示。导出的函数也不能移植到非bash shell。OP非常清楚,问题是专门要求一个能在POSIX基线平台上工作的解决方案(而且我们已经有很多几乎重复的解决方案没有这一要求)。FWIW,我觉得POSIX xargs这样做绝对是可笑的,甚至是危险的。@TorstenBronger,…老实说,缺少一些
-r
等效物可能是POSIXxargs设计缺陷中危险最小的;与类似于shell(但与shell不完全兼容)的输入解析或允许实现执行子字符串扩展(从而鼓励
xargs-I{}sh-c'{}…'
使用模式,并伴随shell注入风险)相比,它的安全性要低得多.从问题的最后一行开始:我的xargs不接受
-r
-如果参数为空则不运行,正如在对未指定POSIX合规性的相关问题的回答中所建议的那样。类似地,当他们指定严格的POSIX合规性时,导出的函数也被淘汰了。我不确定
handle\u empty
是否真的符合您的要求。管道的所有部分同时运行--
handle_empty
函数退出并不意味着
xargs
不运行(或阻止
xargs
在没有输入的情况下被调用;因此,如果根本没有输入,则从一开始就不会进入
while read
循环),它只是确保xargs看不到输入中超过第一个空行的任何内容。