我想从远程服务器删除多个文件。我将所有文件放在一个脚本中的一个数组下,然后调用其他脚本来删除文件。
设“${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
将删除文件的脚本是:
#!/bin/bash
file="$1"
sshpass -p 'password' ssh [email protected] "echo "$file""
打电话时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
并且在调用时bash /tmp/1.sh "${b[@]}"
它仅将一个文件分配给文件变量。
/mnt/DataBK/BackupDropwizardLogs_2015-12-17_04-00-01.tar.gz
有人可以告诉我如何将包含空格的数组的值分配给上面脚本中的文件变量吗?
更新::它通过declare -a file=("$@")
在其他脚本中设置来工作。但是如果想发送更多参数而不仅仅是数组怎么办?
答案1
sshpass -p 'password' ssh [email protected] "some_cmd $(printf '%q ' "$@")"
sshpass -p 'password' ssh [email protected] "f() { for i; do some_cmd "$i"; done; }; f $(printf '%q ' some_cmd "$@")"
根据 sshpass 手册页,
sshpass [-ffilename|-dnum|-ppassword|-e] [options] command arguments
因此,您应该能够将所有内容传递"$@"
到 ssh 命令中,例如:
sshpass -p 'password' ssh [email protected] printf '%q\n' "$@"
由于您的目标命令可能无法处理此类参数处理,因此我们可以解决此问题:
sshpass -p 'password' 'k(){ for i; do echo $i; done; }; k' "$@"
让我们用一些空格来测试......
set -- 'foo bar' $'lorem\nipsum\td'
# paste that two lines.. Since I don't have sshpass installed, just using ssh.
ssh
显然搞砸了。让我们插入一些伪造的外壳,看看会发生什么。
#!/bin/bash
# /bin/mysh
# someone:x:1000:1000:FOo,,Bar,:/home/foo:/bin/mysh
printf '%q ' bash "$@"; echo;
exec bash -xv --norc "$@";
唔。咱们试试吧。
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
显然 ssh 只是将这些东西与空格连接在一起。不酷。
让我们用 预先转义它printf '%q '
,你会得到TL; DR回答。现在您也可以了解 EOF 和-c
失败了。
注意:我不确定 ssh 在不同版本中是否以不同的方式执行 -c 操作。您可能需要自己尝试一下。至少对于 OpenSSH 7.1 来说是这样(ssh.c:955-969)。
答案2
回答你的问题的标题:
通过 [脚本] 将多个带有空格的参数传递到 ssh
我建议避开引号:
ssh [email protected] echo "\"arg 1\" \"arg 2\""
"arg 1"
...将作为第一个参数和第二个参数发送"arg 2"
,在本例中发送到远程计算机上的 echo 命令,从而产生输出:
arg 1 arg 2
注意:命令 echo 输出各个参数,参数之间有一个空格。但是,单个参数中包含的(多个)空格将被保留。将此作为证据,证明空白实际上是参数的一部分,这是问题标题中所要求的。
答案3
第一个脚本应该类似于:
#!/bin/bash
password="mypassword"
filelist=("$@")
for file in "${filelist[@]}";
do
sshpass -p '$password' ssh [email protected] "echo \"$file\""
done
for 循环会将每个文件呈现给命令。
至于错误:
bash: -c: line 0: unexpected EOF while looking for matching `''
我假设它与您调用脚本的方法有关。你应该这样称呼它(一行):
$ ./1.sh "${b[@]}"