Linux 防止ssh破坏shell脚本参数
我有一个脚本,它本质上是在不同机器上以相同名称围绕可执行文件的包装器。为了举例,我将在这里包装printf。我当前的脚本如下所示:Linux 防止ssh破坏shell脚本参数,linux,bash,ssh,Linux,Bash,Ssh,我有一个脚本,它本质上是在不同机器上以相同名称围绕可执行文件的包装器。为了举例,我将在这里包装printf。我当前的脚本如下所示: #!/bin/bash ssh user@hostname.tld. printf "$@" ./wrap_printf "%s\e[39m\e[49m\n" $'\e[30m\e[42mBlack on Green' "Just Normal Text" 不幸的是,当其中一个参数包含空格时,这会中断,例如,我希望以下命令提供相同的输出: ~$ ./wrap_p
#!/bin/bash
ssh user@hostname.tld. printf "$@"
./wrap_printf "%s\e[39m\e[49m\n" $'\e[30m\e[42mBlack on Green' "Just Normal Text"
不幸的是,当其中一个参数包含空格时,这会中断,例如,我希望以下命令提供相同的输出:
~$ ./wrap_printf "%s_%s" "hello world" "1"
hello_world1_
~$ printf "%s_%s" "hello world" "1"
hello world_1
当涉及(转义的)换行时,问题变得更糟。我怎样才能正确地避开这里的争论呢
#!/bin/sh
QUOTE_ARGS=''
for ARG in "$@"
do
QUOTE_ARGS="${QUOTE_ARGS} '${ARG}'"
done
ssh user@hostname.tld. "${QUOTE_ARGS}"
这适用于空间。如果参数中嵌入了单引号,则不起作用。基于Peter Lyons的答案,但也允许在参数中使用引号:
#!/bin/bash
QUOTE_ARGS=''
for ARG in "$@"
do
ARG=$(printf "%q" "$ARG")
QUOTE_ARGS="${QUOTE_ARGS} $ARG"
done
ssh user@hostname.tld. "printf ${QUOTE_ARGS}"
这适用于到目前为止我测试过的所有内容,除了新行:
$ /tmp/wrap_printf "[-%s-]" "hello'\$t\""
[-hello'$t"-]
正确地引用是相当困难的,而在bash中(以一种通用而健壮的方式)这样做几乎是不可能的 使用Perl:
#!/usr/bin/perl
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new('user@hostname');
$ssh->system('printf', @ARGV);
根据Koert和Peter Lyons的回答,这里是ssh的包装器;我称之为“sshsystem”。(亦可于
最简单、最快速的方法就是使用Bash的引用参数转换:
${parameter@Q}
。这可以在使用${array[@]@Q}
进行数组扩展时自动应用,但在使用内置参数数组时,名称和括号会被删除,因此它会变成${@Q}
。因此,原始脚本只需添加4个字符即可工作
#!/bin/bash
ssh user@hostname.tld. printf "${@@Q}"
现在,任何转义都可以工作,即使是这样的终端颜色:
#!/bin/bash
ssh user@hostname.tld. printf "$@"
./wrap_printf "%s\e[39m\e[49m\n" $'\e[30m\e[42mBlack on Green' "Just Normal Text"
那会有用的,谢谢。我将发布一个额外的答案,这也解决了引号问题。似乎对换行符也有效(尽管换行符如果出现在错误的位置,会在终端上引起其他奇怪的显示怪癖)