运行远程脚本的意外行为

时间:2018-11-21 09:02:19

标签: linux bash shell ssh centos6

我正在尝试编写在远程计算机上运行的脚本。

由于该脚本很复杂,因此我将其分解成一些函数,然后使用typeset复制到了脚本中。

运行脚本时,出现以下错误:

bash: -c: line 4: syntax error: unexpected end of file

但是,文件没有意外结束!我确保所有if都有fi,所有{都有},等等。

我确保所有缩进都使用制表符(和空格),并确保换行符一致。

我已将代码简化为一个最小的示例。似乎某个函数有效,它需要以if fiwhile done之类的构造结尾。

这是行不通的。

func() {
  ls ~/
}

ssh -A -T user@machine_ip '
'$(typeset -f func)'
func
'

第4行与}函数的结尾func重合(因为在远程计算机上发生此错误,因此对ssh -A -T...之后的行进行计数)。

但是,如果我们在函数末尾添加一个构造,则会按预期方式打印主目录。

func() {
    ls ~/
    if [[ 1 ]]; then
      echo "Hello"
    fi
}

func() {
    ls ~/
    while false; do
        echo "Here"
    done
}

typeset -f func的输出是

func () 
{ 
    ls --color=auto ~/;
    if [[ -n 1 ]]; then
        echo "Hello";
    fi
}

我正在运行Ubuntu 18.04 LTS,远程计算机正在运行Centos 6。

2 个答案:

答案 0 :(得分:1)

因为如果让bash玩空格,它就会发挥作用。让我解释一下:

$(typeset -f func)将求值typeset -f func并将其输出插入当前命令行。如果不加引号,它也将细分为参数,这将使所有空白折叠为一个空格,这是一个副作用。因此,如果typeset -f func可以打印(就像在我的系统上一样)

func () 
{ 
    /bin/ls --color=auto ~/
}

$(typeset -f func)带来的好处

func () { /bin/ls --color=auto ~/ }

(如果您不相信我,请尝试echo $(typeset -f func):D)

现在,bash对于接受模糊的代码确实很害羞。例如,您可能知道这不是语法上的:

if true then echo "yes" fi

这是:

if true; then echo "yes"; fi

以同样的方式,函数定义的右括号很挑剔。因此,这可行:

func () { /bin/ls --color=auto ~/; }

但这不是:

func () { /bin/ls --color=auto ~/ }

由于某种原因,bash可以使用括号前的关键字作为罚款。

func () { /bin/ls --color=auto ~/; if [[ -n 1 ]]; then echo "Hello"; fi }
func () { /bin/ls --color=auto ~/; while false; do echo "Here"; done }

要解决这个问题,请尝试不要从命令行发送东西,而是从重定向发送东西,

ssh -A -T user@machine_ip < <(typeset -f func; echo func)

或者最简单的方法是,使用双引号防止bash空格的倒角:

ssh -A -T user@machine_ip "$(typeset -f func)
func"

答案 1 :(得分:0)

首先,引号的使用方式对我来说毫无意义。

ssh -A -T user@machine_ip '
'$(typeset -f func)'
func
'

第2个'仅回显一个空行。 (第二个'关闭第一个逻辑?)

反正。

$(typeset -f func)
func

上面的代码将执行func 2次。 至少这就是它对我有效的方式

....