我被这段代码困住了
user@server:~$ TEST="ssh [email protected] 'date; hostname -A; uname -a'"
user@server:~$ $TEST
bash: date; hostname -A; uname -a: Command not found.
我想在 shell 脚本中使用它,但不知道问题出在哪里。两个系统都是 debian wheezy,
但如果直接执行命令:
user@server:~$ ssh [email protected] 'date; hostname -A; uname -a'
Fre Aug 23 20:02:55 CEST 2013
otherserver.example.org
Linux otherserver 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64 GNU/Linux
那么这有什么大不了的???我转述说我遗漏了一些非常琐碎的事情,但就是想不出来……请帮忙……
这背后的想法是,我在脚本中建立一个长字符串,并在单个 SSH 会话中远程执行它(将所有 zfs 快照重命名为 n.0 变为 n.1 等等)
但它不工作,希望它工作......
编辑/更新:更新了示例以便更好地理解我的问题(从'日期;日期;日期'到'日期;主机名-A;uname-a')
感谢到目前为止的所有回复。起初 eval 可以工作,但正如用户所说,它似乎已被弃用。所以我的工作是再次弄清楚如何更改它。
所构建的字符串看起来类似于以下内容:
echo "Rearanging snapshots..."
last_backup=7
first_backup=0
RENAME_STRING="'sudo zfs destroy $BACKUP_DATASTORE@n.$last_backup; "
while [ $last_backup -gt $first_backup ]
do
RENAME_STRING=$RENAME_STRING"sudo zfs rename $BACKUP_DATASTORE@n.$(($last_backup - 1)) $BACKUP_DATASTORE@n.$last_backup"
if [ $(($last_backup - 1 )) -gt $first_backup ]
then
RENAME_STRING=$RENAME_STRING"; "
else
RENAME_STRING=$RENAME_STRING"'"
fi
last_backup=$(($last_backup - 1 ))
done
#CURRENTLY SOLVED WITH EVAL as this one doesn't work...
#remote_cmd=(/usr/bin/ssh "$BACKUP_USER@$HOST_TO" "$RENAME_STRING")
#"${remote_cmd[@]}"
eval /usr/bin/ssh $BACKUP_USER@$HOST_TO $RENAME_STRING
那么也许你们有更优雅的方法来解决这个问题?
编辑2:
这个输出“OK”吗?(OK 是指不被弃用,并且可以使用吗?
user@server:~$ TEST="date ; hostname -A ; uname -a"
user@server:~$ ssh [email protected] <<< "$(printf '%s ' $TEST)"
Pseudo-terminal will not be allocated because stdin is not a terminal.
Linux otherserver 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Fre Aug 23 20:13:53 CEST 2013
otherserver.example.org
Linux otherserver 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64 GNU/Linux
EDI3:已更新/改进(?)但循环 eval 仍然使用,因为 <<< 在脚本中不起作用......
答案1
通过 ssh 远程执行本地命令的建议方法是不要使用 eval。不建议这样做。由于您要将整行存储在变量中,因此您可以
mydate=$(date; date; date);
ssh [email protected] bash <<< "$(printf 'echo %q ' "$mydate")"
Eval 只应该在不提供安全工具(如我向您展示的示例)的遗留系统中使用。
这会产生与您使用交互式 shell 运行这些命令完全相同的结果。
希望它至少能给你一些想法。
更新以演示如何让命令也能远程运行,而无需定义本地变量。
ssh [email protected] bash <<< "$(printf '%s ' "whoami && ps aux")"
答案2
尝试 shell/bash 内置评估命令:
$ help eval
eval: eval [arg ...]
Execute arguments as a shell command.
Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.
Exit Status:
Returns exit status of command or success if command is null.
答案3
没有必要编写这么长的命令串来通过 SSH 运行。只需在远程主机上创建一个永久脚本,然后使用/usr/local/sbin/rotate_backups
调用它即可ssh $USER@$HOST 'sudo /usr/local/sbin/rotate_backups'
。
如果你在“Unix 和 Linux”StackExchange,那么这可能是一个有趣的问题。但是,作为系统管理员,您的目标应该是可维护性和安全性。如果您无法理解脚本,您的同事和继任者会骂您。
答案4
发现问题
我用一根单线开始我的长串'
,用一根单线结束我的长串'
现在我保留所有单引号('
),自己创建字符串并在末尾添加双引号,全部有效!
#!/bin/sh
...
#[SOME_CODE_HERE]
...
echo "Rearanging snapshots..."
last_backup=7
first_backup=0
RENAME_STRING="sudo zfs destroy $BACKUP_DATASTORE@n.$last_backup; "
while [ $last_backup -gt $first_backup ]
do
RENAME_STRING=$RENAME_STRING"sudo zfs rename $BACKUP_DATASTORE@n.$(($last_backup - 1)) $BACKUP_DATASTORE@n.$last_backup; "
last_backup=$(($last_backup - 1 ))
done
/usr/bin/ssh $BACKUP_USER@$HOST_TO "$RENAME_STRING"
那么有人可以向我解释一下,为什么我不能设置变量内的引号?
现在这个构造工作得很好。谢谢大家的帮助!希望我的回答也能帮助到别人!(ALL_CAPITAL 的事情稍后会解决 ;) )