traceroute 和 traceroute6 到 运行 的最短 shell 代码

Shortest shell code to run both traceroute and traceroute6

我想 运行 traceroute -w2traceroute6 -w2,在 shell 脚本中顺序地尝试多个不同的主机。

一种天真的方法可能只是使用一个临时变量来收集其中的所有主机(例如,将 HOSTS 设置为 ordns.he.net one.one.one.one google-public-dns-a.google.com),然后将其单独传递给每个命令,例如 echo $HOSTS | xargs -n1 traceroute -w2 等,但这在 tcsh 中的工作方式与在 bash 中的工作方式不同,并且如果您想添加更多命令(因为您将把它们作为代码添加为反对要做的事情列表),我认为有一些更好的方法可以将 命令列表 连接在一起(例如,一个带有单个参数的命令名称)和 参数列表 (例如,我们示例中的主机名),以便 shell 执行每一种可能的组合。

我试过将 xargs -n1(对于主机)和 xargs -n2(对于带有一个参数的命令)进行一些组合,但它并没有多大意义而且没用。

我正在寻找一个不使用任何 GNU 工具并且可以在基础 OpenBSD 安装中工作的解决方案(如果需要,perl 是基础 OpenBSD 的一部分,因此,它也可用).

保持简单:

#!/bin/sh
set -- host1 host2 host3 host4 ...
for host do traceroute -w2 -- "$host"; done
for host do traceroute6 -w2 -- "$host"; done

如果你有 perl:

perl -e 'for(@ARGV){ print qx{  traceroute -w2 -- $_; traceroute6 -w2 -- $_ } }' google.com debian.org

至于将命令列表(例如,带有单个参数的命令名称)与参数列表(例如,主机名)连接在一起的更好方法,答案可能是 GNU Parallel,它是为做就是这样:

parallel "{1}" -w2 -- "{2}" ::: traceroute traceroute6 ::: google.com debian.org

如果你想要特殊参数与每个命令相关联,你可以这样做:

parallel eval "{1}" -- "{2}" ::: "traceroute -a -w2" "traceroute6 -w2" ::: google.com debian.org

eval 是必需的,因为 GNU Parallel 引用了所有输入,虽然您通常需要它,但在这种情况下我们不希望它。

但是因为这是一个 GNU 工具,所以它不在你的问题范围之内。它仅包含在此处供阅读您的问题且没有该限制的其他人使用。

使用 GNU Parallel, the final solution for the problem at stake would be something like the following snippet, using tcsh 语法,以及 OS X traceroutetraceroute6:

( history 1 ; parallel --keep-order -j4 eval \{1} -w1 -- \{2} '2>&1' ::: "traceroute -a -f1" traceroute6 ::: ordns.he.net ns{1,2,3,4,5}.he.net one.one.one.one google-public-dns-a.google.com resolver1.opendns.com ; history 1 ) | & mail -s "traceroute: ordns.he.net et al from X" receipient@example.org -f sender@example.org