我正在编写一个脚本来恢复一组服务器上的Master-Slave复制。在bash语法中丢失,试图分配一个局部变量,其结果是远程运行命令替换为本地值:
function doRemote() {
ssh s1.domain.com <<ENDSSH
mysql -u root -pXXX --execute="DROP DATABASE db; CREATE DATABASE db;"
mysql -u root -pXXX --database=db < $WORKDIR$FILENAME
sudo rm -rf /var/log/mysql/db-bin.*
mysql -u root -pXXX --execute="FLUSH LOGS;"
CURRENT_LOG=`mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $1}'`
CURRENT_POS=`mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $2}'`
# ...
ENDSSH
}
分配CURRENT_ *变量的两行是问题:mysql -u...
命令在本地执行,而不是远程会话。
请建议如何远程运行,使用远程mysql命令的结果分配本地变量。
答案 0 :(得分:6)
尝试转义ENDSSH
,如下所示,以便在远程主机上进行变量评估:
ssh s1.domain.com <<\ENDSSH
# ...
ENDSSH
答案 1 :(得分:2)
尝试转义您的cmd替换调用
CURRENT_LOG=`mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $1}'`
现在是
CURRENT_LOG=\`mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $1}'\`
或加入90年代;-)并使用$( ... )
形式的cmd替换(也转义)
CURRENT_LOG=\$(mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $1}' )
您可能必须使用多个'\'
字符才能正确转义。
IHTH
答案 2 :(得分:2)
所以,你有两个完全不同的问题:
ssh
之前,您打算远程运行,作为通过ssh
传递的输入的一部分。其他答案已经涵盖#1(即:更好的逃避),所以我将覆盖#2号。
#2很棘手,但一种方法是将ssh
命令修改为 print 需要在本地运行的赋值语句。然后,您可以将其包装在运行这些赋值语句的eval
命令中。
总而言之,你最终会得到这样的结论:
function doRemote() {
eval "$(ssh s1.domain.com <<' ENDSSH'
mysql -u root -pXXX --execute="DROP DATABASE db; CREATE DATABASE db;" >&2
mysql -u root -pXXX --database=db < $WORKDIR$FILENAME >&2
sudo rm -rf /var/log/mysql/db-bin.* >&2
mysql -u root -pXXX --execute="FLUSH LOGS;" >&2
printf 'CURRENT_LOG=%q\n' `mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $1}'`
printf 'CURRENT_POS=%q\n' `mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $2}'`
# ...
ENDSSH)"
}
(注意我向所有以前的命令添加了>&2
,因此它们的输出变为标准错误而不是标准输出。这是因为标准输出被捕获并且eval
在本地输出,显然你不想要。)
答案 3 :(得分:0)
doRemote() {
ssh localhost <<ENDSSH
ls
cat /etc/issue
VAR1=\$(/home/thumper/bash/test2.sh)
echo \$VAR1 >> /home/thumper/bash/test.txt
ENDSSH
}
doRemote
答案 4 :(得分:0)
也可以将整个here文档的内容存储在变量中,然后将此变量作为参数传递给ssh
命令。
添加一些echo
语句可以访问本地计算机上的${CURRENT_LOG}
和${CURRENT_POS}
变量。只需确保下面的$ssh_output
仅包含echo
语句的输出(另请参阅:Run a parallel command while waiting for ssh)。
如果ssh
要执行sudo
提示输入密码,请不要从此处的文档重定向stdin。
# untested
function doRemote() {
cmds="$(cat <<'ENDSSH'
mysql -u root -pXXX --execute="DROP DATABASE db; CREATE DATABASE db;"
mysql -u root -pXXX --database=db < $WORKDIR$FILENAME
sudo rm -rf /var/log/mysql/db-bin.*
mysql -u root -pXXX --execute="FLUSH LOGS;"
CURRENT_LOG=`mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $1}'`
echo "export CURRENT_LOG='${CURRENT_LOG}';"
CURRENT_POS=`mysql -u root -pXXX --execute="SHOW MASTER STATUS" -AN | awk '{print $2}'`
echo "export CURRENT_POS='${CURRENT_POS}';"
# ...
ENDSSH
)"
# use ssh -t for sudo command
ssh_output="$(ssh -t s1.domain.com "$cmds")"
eval "$ssh_output"
return 0
}