将变量传递给子 shell 时出现问题
Having an issue passing variables to subshell
所以这是我的问题,我写了这个脚本,我在其中导出两个变量,但是它们没有进入子 shell。
此脚本的目的是更改用户密码并清除其 pam_tally 的 CentOS 和 Ubuntu 主机。
一点背景是这个环境的用户由 puppet 管理,但密码都是本地的,ssh 密钥也不允许(这是一成不变的,无法更改,所以我必须使用我的东西得到了),原因是每次登录都必须是手动的(即使会话数也限制为两个,所以你甚至不能有效地使用 csshX)。
这是我的脚本
#!/bin/bash
echo "Please enter user whose password you want to change"
read NEWUSER
echo "Please enter new password for user"
read -s -p "Temp Password:" TEMPPASSWORD
PASSWORD=$TEMPPASSWORD
export PASSWORD
NEWUSER2=$NEWUSER
export NEWUSER2
for i in HOST{cluster1,cluster2,cluster3}0{1..9}
do
ping -c 2 $i && (echo $i ; ssh -t $i '
sudo pam_tally2 --user=$NEWUSER2 --reset
echo -e "$PASSWORD\n$PASSWORD" | sudo passwd $NEWUSER2
sudo chage -d 0 $NEWUSER2
')
done
您正在使用 ssh
连接到远程主机并 运行 该主机上的脚本。 ssh
不会将本地环境导出到远程会话,而是在远程主机上执行登录,根据远程用户在远程主机上的配置设置环境。
我建议您通过要执行的 命令 传递所有需要的值。可以这样做:
ssh -t $i '
sudo pam_tally2 --user='"$NEWUSER2"' --reset
echo -e "'"$PASSWORD"'\n'"$PASSWORD"'" | sudo passwd '"$NEWUSER2"'
sudo chage -d 0 '"$NEWUSER2"
仔细观察这是如何使用引号的。在每次使用变量的情况下,我都会终止单引号字符串(使用 '
),然后添加对变量的双引号使用(例如 "$PASSWORD"
),然后开始使用单引号再次使用字符串(再次使用 '
)。这样,执行 ssh
命令的 shell 将已经扩展变量,因此您无需将它们传递到远程 shell.
但请注意,密码中的特殊字符(如 "
或 '
或 </code> 或可能是一堆其他字符)可能会导致使用困难这个简单的机制。为了避免这种情况,您需要使用 <code>printf
命令的 %q
格式说明符在传递您的值之前引用它们:
ssh -t "$i" "$(printf '
sudo pam_tally2 --user=%q --reset
{ echo %q; echo %q; } | sudo passwd %q
sudo chage -d 0 %q' \
"$NEWUSER2" "$PASSWORD" "$PASSWORD" "$NEWUSER2" "$NEWUSER2")"
所以这是我的问题,我写了这个脚本,我在其中导出两个变量,但是它们没有进入子 shell。
此脚本的目的是更改用户密码并清除其 pam_tally 的 CentOS 和 Ubuntu 主机。
一点背景是这个环境的用户由 puppet 管理,但密码都是本地的,ssh 密钥也不允许(这是一成不变的,无法更改,所以我必须使用我的东西得到了),原因是每次登录都必须是手动的(即使会话数也限制为两个,所以你甚至不能有效地使用 csshX)。
这是我的脚本
#!/bin/bash
echo "Please enter user whose password you want to change"
read NEWUSER
echo "Please enter new password for user"
read -s -p "Temp Password:" TEMPPASSWORD
PASSWORD=$TEMPPASSWORD
export PASSWORD
NEWUSER2=$NEWUSER
export NEWUSER2
for i in HOST{cluster1,cluster2,cluster3}0{1..9}
do
ping -c 2 $i && (echo $i ; ssh -t $i '
sudo pam_tally2 --user=$NEWUSER2 --reset
echo -e "$PASSWORD\n$PASSWORD" | sudo passwd $NEWUSER2
sudo chage -d 0 $NEWUSER2
')
done
您正在使用 ssh
连接到远程主机并 运行 该主机上的脚本。 ssh
不会将本地环境导出到远程会话,而是在远程主机上执行登录,根据远程用户在远程主机上的配置设置环境。
我建议您通过要执行的 命令 传递所有需要的值。可以这样做:
ssh -t $i '
sudo pam_tally2 --user='"$NEWUSER2"' --reset
echo -e "'"$PASSWORD"'\n'"$PASSWORD"'" | sudo passwd '"$NEWUSER2"'
sudo chage -d 0 '"$NEWUSER2"
仔细观察这是如何使用引号的。在每次使用变量的情况下,我都会终止单引号字符串(使用 '
),然后添加对变量的双引号使用(例如 "$PASSWORD"
),然后开始使用单引号再次使用字符串(再次使用 '
)。这样,执行 ssh
命令的 shell 将已经扩展变量,因此您无需将它们传递到远程 shell.
但请注意,密码中的特殊字符(如 "
或 '
或 </code> 或可能是一堆其他字符)可能会导致使用困难这个简单的机制。为了避免这种情况,您需要使用 <code>printf
命令的 %q
格式说明符在传递您的值之前引用它们:
ssh -t "$i" "$(printf '
sudo pam_tally2 --user=%q --reset
{ echo %q; echo %q; } | sudo passwd %q
sudo chage -d 0 %q' \
"$NEWUSER2" "$PASSWORD" "$PASSWORD" "$NEWUSER2" "$NEWUSER2")"