通过脚本将多个带有空格的参数传递给 ssh

AVJ*_*AVJ 5 bash ssh array shell-script quoting

我想从远程服务器中删除多个文件。我在脚本中的一个数组下拥有所有文件,我调用其他脚本来删除文件。

让“${b[@]}”的输出为:

/mnt/DataBK/BackupDropwizardLogs_2015-12-17_04-00-01.tar.gz
/mnt/DataBK/BackupDropwizardLogs_2015-12-17_04-30-01.tar.gz
/mnt/DataBK/BackupDropwizardLogs_2015-12-17_05-00-02.tar.gz
Run Code Online (Sandbox Code Playgroud)

将删除文件的脚本是:

#!/bin/bash  
file="$1"  
sshpass -p 'password' ssh user@192.168.3.3 "echo "$file""
Run Code Online (Sandbox Code Playgroud)

打电话时bash /tmp/1.sh "'${b[@]}'"出现错误

bash: -c: line 0: unexpected EOF while looking for matching `''  
bash: -c: line 1: syntax error: unexpected end of file
Run Code Online (Sandbox Code Playgroud)

并且在调用bash /tmp/1.sh "${b[@]}" 它时只将一个文件分配给文件变量。
/mnt/DataBK/BackupDropwizardLogs_2015-12-17_04-00-01.tar.gz

有人可以告诉我如何将包含空格的数组的值分配给上述脚本中的文件变量。

更新:: 它通过declare -a file=("$@")在其他脚本中设置来工作。但是如果想发送更多的参数而不是只发送数组呢?

Min*_*ang 6

sshpass -p 'password' ssh user@192.168.3.3 "some_cmd $(printf '%q ' "$@")"
sshpass -p 'password' ssh user@192.168.3.3 "f() { for i; do some_cmd "$i"; done; }; f $(printf '%q ' some_cmd "$@")"
Run Code Online (Sandbox Code Playgroud)

根据 sshpass 联机帮助页,

sshpass [-ffilename|-dnum|-ppassword|-e] [options] command arguments

因此,您应该能够将所有内容传递"$@"给 ssh 命令,例如:

sshpass -p 'password' ssh user@192.168.3.3 printf '%q\n' "$@"
Run Code Online (Sandbox Code Playgroud)

由于您的目标命令可能无法处理这样的参数处理,我们可以解决这个问题:

sshpass -p 'password' 'k(){ for i; do echo $i; done; }; k' "$@"
Run Code Online (Sandbox Code Playgroud)

让我们用一些空格来测试...

set -- 'foo bar' $'lorem\nipsum\td'
# paste that two lines.. Since I don't have sshpass installed, just using ssh.
Run Code Online (Sandbox Code Playgroud)

ssh显然搞砸了。让我们插入一些伪造的外壳,看看发生了什么..

#!/bin/bash
# /bin/mysh
# someone:x:1000:1000:FOo,,Bar,:/home/foo:/bin/mysh
printf '%q ' bash "$@"; echo;
exec bash -xv --norc "$@";
Run Code Online (Sandbox Code Playgroud)

唔。咱们试试吧。

bash -c $'printf %q\\n foo bar lorem\nipsum\td'
printf %q\n foo bar lorem
+ printf %qn foo bar lorem
ipsum   d
+ ipsum d
bash: line 1: ipsum: command not found
Run Code Online (Sandbox Code Playgroud)

所以显然 ssh 只是将这些东西与空格连接在一起。不酷。

让我们用 预先转义它printf '%q ',您将获得TL;博士回答。现在您也可以弄清楚 EOF 和-c失败。

注意:我不确定 ssh 是否在版本之间对 -c 的处理有所不同。您可能需要自己尝试一下。至少对于 OpenSSH 7.1 ( ssh.c:955-969 ) 来说是这样。


小智 0

第一个脚本应该类似于:

#!/bin/bash
password="mypassword"
filelist=("$@")

for file in "${filelist[@]}";
do 
    sshpass -p '$password' ssh user@192.168.3.3 "echo \"$file\""
done
Run Code Online (Sandbox Code Playgroud)

for 循环会将每个文件呈现给命令。


至于错误:

bash: -c: line 0: unexpected EOF while looking for matching `''
Run Code Online (Sandbox Code Playgroud)

我假设它与您调用脚本的方法有关。你应该这样称呼它(一行):

$ ./1.sh "${b[@]}"
Run Code Online (Sandbox Code Playgroud)