debian bash/sh 字符串执行

debian bash/sh 字符串执行

我被这段代码困住了

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 的事情稍后会解决 ;) )

相关内容