Linux 防止ssh破坏shell脚本参数

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

我有一个脚本,它本质上是在不同机器上以相同名称围绕可执行文件的包装器。为了举例,我将在这里包装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_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"

那会有用的,谢谢。我将发布一个额外的答案,这也解决了引号问题。似乎对换行符也有效(尽管换行符如果出现在错误的位置,会在终端上引起其他奇怪的显示怪癖)