函数ping +()到.bashrc中不起作用

时间:2018-11-28 19:56:27

标签: bash function windows-subsystem-for-linux

我有这个问题。 我的机器是Windows 10最新版本。

我安装了cygwin,并在我的bashrc中安装了此功能:

ping+()
{
        host=$1
        par_1=$2
        par_2=$3
        par_3=$4
        ping $host $par_1 $par_2 $par_3 | xargs -n1 -i bash -c 'echo [`date +"%Y-%m-%d | %H:%M:%S"`] " {}"'
}

工作正常:

Luca[~] :> ping+ www.google.it
[2018-11-28 | 20:41:23]  Pinging www.google.it [74.125.71.94] with 32 bytes of data:
[2018-11-28 | 20:41:23]  Reply from 74.125.71.94: bytes=32 time=28ms TTL=43
[2018-11-28 | 20:41:24]  Reply from 74.125.71.94: bytes=32 time=31ms TTL=43
[2018-11-28 | 20:41:25]  Reply from 74.125.71.94: bytes=32 time=29ms TTL=43
[2018-11-28 | 20:41:26]  Reply from 74.125.71.94: bytes=32 time=29ms TTL=43
[2018-11-28 | 20:41:26]  Ping statistics for 74.125.71.94:
[2018-11-28 | 20:41:26]  Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
[2018-11-28 | 20:41:26]  Approximate round trip times in milli-seconds:
[2018-11-28 | 20:41:26]  Minimum = 28ms, Maximum = 31ms, Average = 29ms

但是,如果我将此代码放入“ ubuntu Windows文件系统”上的.bashrc中,则会收到此错误:

luca[/mnt/c/Users/Luca] :> source /home/luca/.bashrc
ping+(): command not found

“ ping”后的“ +”很可能不被接受。 我该如何解决这个问题? 谢谢 路卡

1 个答案:

答案 0 :(得分:1)

这是外壳函数之间相互作用的结果,这些函数的名称中带有'+'字符,而bash的extglob选项也是如此。您很有可能在Cygwin下的外壳中禁用了extglob,并在“ ubuntu Windows文件系统”配置中启用了此功能。

我还没有弄清楚为什么extglob有这种特殊的副作用。这可能是bash中的错误。 bash接受ping+作为函数名称甚至可能是一个错误,具体取决于相关标准和其他文档对函数名称的正确语法的说明。

最简单的解决方案是使用不以+字符结尾的名称。

如果您确实要为函数使用名称ping+,则解决方法是在定义函数时取消设置extglob选项。 (无论是否设置了ping+,您仍然可以使用名称extglob来调用它。)

例如,您可以在.bashrc中放置它:

shopt -u extglob
ping+() {
    host=$1
    par_1=$2
    par_2=$3
    par_3=$4
    ping $host $par_1 $par_2 $par_3 | xargs -n1 -i bash -c 'echo [`date +"%Y-%m-%d | %H:%M:%S"`] " {}"'
}
shopt -s extglob

(这会强制设置extglob。如果要将其保留为初始状态,则要复杂一些。您必须解析shopt extglob的输出以确定它是否为设置或未设置。但是您可能还是想无条件设置它。)

另一种解决方案是使用可执行的Shell脚本而不是函数。例如,此脚本等效于您的功能:

#!/bin/bash

host="$1"
par_1="$2"
par_2="$3"
par_3="$4"
ping $host $par_1 $par_2 $par_3 | xargs -n1 -i bash -c 'echo [`date +"%Y-%m-%d | %H:%M:%S"`] " {}"'

使用上述内容创建一个名为ping+的文件,使其可以用chmod +x执行,然后将其复制到$PATH中的目录中,例如$HOME/bin。 (无需将其安装在系统目录中,例如/usr/bin。如果希望系统上的所有用户都可以使用它,则可以将其安装在系统范围的目录中,例如/usr/local/bin/usr/bin目录用于操作系统本身提供的命令。)

之所以行之有效,是因为命令名称的规则比shell函数名称的规则更简单,限制更少。

这是一个更简单,更可靠的版本(它避免了参数中shell元字符的任何问题)。

#!/bin/bash

ping "$@" | xargs -n1 -i bash -c 'echo [`date +"%Y-%m-%d | %H:%M:%S"`] " {}"'

或更妙的是(由于xargs可以启用命令替换攻击,如Charles Duffy指出的那样):

#!/bin/bash

ping "$@" | while read -r line ; do echo "[$(date +'%Y-%m-%d | %H:%M:%S')] $line" ; done