我正在尝试编写一个通过 ssh 运行远程脚本的 bash 脚本,如下所示:
#!/bin/bash
logfilepattern="*drupal*.gz php*.gz error*.gz"
function getlogcounts {
echo "in getlogcounts"
echo $1
echo $2
ssh $1 bash -c ' \ #script string starts here
cd $2
for file in `ls $logfilepattern`
do
ls -l $file
done
'
}
getlogcounts [email protected] "/var/log/mylogs"
$1
并且$2
似乎在函数中遇到了 ok,但在脚本字符串内它们似乎没有值...因此cd $2
评估为cd
并ls $logfilepattern
评估为ls
。
答案1
这是一个经过简化的版本,更重要的是,引用已得到纠正(变量周围用双引号,需要时非变量文本周围用单引号)
#!/bin/bash
logfilepattern='*drupal*.gz php*.gz error*.gz'
function getlogcounts {
echo in getlogcounts
echo "$1"
echo "$2"
ssh "$1" "cd $2 ; ls -l $logfilepattern"
}
getlogcounts [email protected] /var/log/mylogs
答案2
您正在远程计算机上执行脚本。该脚本恰好包含$2
and $logfilepattern
(单引号之间的文本按字面意思作为参数传递给命令ssh
,因此它是在另一侧执行的代码片段)。这些指的是在删除端运行的 shell 的变量。
实际上,您在远程端运行两个 shell,但没有什么用处。 SSH 总是调用 shell;您可以向其传递多个参数,但它们之间只是用空格连接。远程端的shell执行
bash -c \ #script string starts here
cd $2
…
第一行使用bash
两个参数调用:-c
和一个空格。这会调用 shell 不执行任何操作。远程命令的其余部分在 SSH 调用的 shell 中执行。
做你想做的事情的简单方法是
ssh "$1" "cd $2 && ls -l $logfilepattern"
笔记:
- 解析 的输出
ls
是没有意义的:for file in `ls *`
是一种复杂的书写方式,但如果文件名包含特殊字符,则for file in *
解析输出会中断。ls
$2
和都$logfilepattern
被解析为在远程端执行的脚本的一部分。如果它们包含类似的内容$(touch foo)
,那么将执行该代码段。在这个特定的用例中,这不一定是问题,但您需要注意。- 使用
&&
aftercd
可确保命令失败ssh
时立即返回失败状态cd
。
如果您想通过 SSH 将未修改的内容传递到远程 shell,单独使用命令行是有问题的,因为您传递的任何内容都会在远程端扩展。一种经常有效的技巧(但并非总是如此,这取决于客户端和服务器上的 SSH 配置)是使用名称以LC_
;开头的变量。这些被假定为有关区域设置的信息,并且经常被传输。
LC_DIRECTORY=$2 LC_LOGFILEPATTERN=$logfilepattern ssh "$1" 'cd "$LC_DIRECTORY" && ls -l $LC_LOGFILEPATTERN'
注意引用:
- 在远程计算机上执行的命令是
cd "$LC_DIRECTORY" && ls -l $LC_LOGFILEPATTERN
。使用单引号将该文字文本作为参数传递给ssh
命令。 $LC_DIRECTORY
在远程端执行的脚本中用双引号括起来,以便cd
对变量的内容调用该命令。LC_LOGFILEPATTERN
不是双引号,因为它是一个以空格分隔的通配符模式列表,这正是处理不带引号的变量扩展的方式。
如果您无法传输变量,则需要添加一层引号来保护值包含特殊字符的变量。
q_directory=$(printf %sa "$2" | sed s/\'/\'\\\'\'/g)
q_directory="'${directory%a}'"
q_logfilepattern=$(printf %sa "$logfilepattern" | sed s/\'/\'\\\'\'/g)
q_logfilepattern="'${q_logfilepattern%a}'"
ssh "$1" "logfilepattern=$q_logfilepattern; cd $q_logfilepattern && ls \$logfilepattern"