使用 shell 脚本通过 ssh 进入实例后无法切换到 root 用户
Unable to switch to root user after ssh into the instance using shell script
我有一个方案可以通过多个 VM 节点上的 shell 脚本自动执行手动构建更新过程。
同样,我尝试使用下面的示例脚本首先通过 ssh 进入实例,然后切换到 root 用户以执行进一步的步骤,例如将构建复制到 /var 下的存档目录,然后继续执行后续步骤。
下面是示例脚本,
#!/bin/sh
publicKey='/path/to/publickey'
buildVersion='deb9.deb build'
buildPathToStore='/var/cache/apt/archives/'
pathToHomedir='/home'
script="whoami && pwd && ls -la && whoami && mv ${buildVersion} ${buildPathToStore} && find ${buildPathToStore} | grep deb9"
for var in "$@"
do
copyBuildPath="${publicKey} ${buildVersion} ${var}:/home/admin/"
echo "copy build ==>" ${copyBuildPath}
scp -r -i ${copyBuildPath}
ssh -i $publicKey -t $var "sudo su - & ${script}; " # This shall execute all commands as root
done
所以上面脚本的 CLI 统计数据是这样的
admin //this is the user check
/home/admin
total 48
drwxr-xr-x 6 admin admin 4096 Dec 6 00:28 .
drwxr-xr-x 6 root root 4096 Nov 17 14:07 ..
drwxr-xr-x 3 admin admin 4096 Nov 17 14:00 .ansible
drwx------ 2 admin admin 4096 Nov 23 18:26 .appdata
-rw------- 1 admin admin 5002 Dec 6 17:47 .bash_history
-rw-r--r-- 1 admin admin 220 May 16 2017 .bash_logout
-rw-r--r-- 1 admin admin 3506 Jun 14 2019 .bashrc
-rw-r--r-- 1 admin admin 675 May 16 2017 .profile
drwx------ 4 admin admin 4096 Nov 23 18:26 .registry
drwx------ 2 admin admin 4096 Jun 21 2019 .ssh
-rw-r--r-- 1 admin admin 0 Dec 6 19:42 testFile.txt
-rw------- 1 admin admin 2236 Jun 21 2019 .viminfo
admin
如果我使用 sudo su -c 并删除 &
喜欢:
ssh -i $publicKey -t $var "sudo su -c ${script}; "
然后 whoami returns 用户作为 root 但工作目录仍然打印为 /home/admin而不是 /root
并且下一组命令仍然适用于管理员用户而不是根用户。所以管理员用户没有权限将构建移动到存档目录并安装构建。
使用 & 我想确保在后台完成进一步的步骤。
不确定如何继续进行。现在非常欢迎好的建议:)
当您单独使用 su
时,它会将您留在实际目录中,如果您使用 su -
,它会模拟 root 登录。
你应该写:su - root -c ${script};
"sudo su - & ${script}; "
扩展为:
sudo su - & whoami && pwd && ...
第一个 sudo su -
在后台 运行 。然后执行命令链。
sudo su -c ${script};
扩展为:
sudo su -c whoami && pwd && ...
所以首先sudo su - whoami
被执行,其中运行s whoami
作为root。然后如果这个命令成功,那么pwd
就会被执行。作为普通用户。
使用 ssh 正确传递命令以在远程站点上执行是非常困难的。使用 sudo su
越来越难做到这一点 - 命令将是 triple (或两次?)单词拆分 - 一次通过 ssh,然后通过 shell , 然后 shell 运行 sudo su
.
如果你不需要交互式交流,最好使用带有-s
shell选项的here文档,一些东西(未测试):
# DO NOT store commands to use in a variable.
# or if you do and you know what you are doing, properly quote it (printf "%q ") and run it via eval
script() {
set -euo pipefail
whoami
pwd
ls -la
whoami
mv "$buildVersion" "$buildPathToStore"
find "$buildPathToStore" | grep deb9
}
ssh ... "sudo bash -s" <<EOF
echo "Yay! anything here!"
echo "Note that here document delimiter is not quoted!"
$(
# safely import context to work with
# note how command substitution is executed on host side
declare -f script
# pass variables too!
declare -p buildVersion buildPathToStore buildPathToStore
)
script
EOF
我有一个方案可以通过多个 VM 节点上的 shell 脚本自动执行手动构建更新过程。 同样,我尝试使用下面的示例脚本首先通过 ssh 进入实例,然后切换到 root 用户以执行进一步的步骤,例如将构建复制到 /var 下的存档目录,然后继续执行后续步骤。 下面是示例脚本,
#!/bin/sh
publicKey='/path/to/publickey'
buildVersion='deb9.deb build'
buildPathToStore='/var/cache/apt/archives/'
pathToHomedir='/home'
script="whoami && pwd && ls -la && whoami && mv ${buildVersion} ${buildPathToStore} && find ${buildPathToStore} | grep deb9"
for var in "$@"
do
copyBuildPath="${publicKey} ${buildVersion} ${var}:/home/admin/"
echo "copy build ==>" ${copyBuildPath}
scp -r -i ${copyBuildPath}
ssh -i $publicKey -t $var "sudo su - & ${script}; " # This shall execute all commands as root
done
所以上面脚本的 CLI 统计数据是这样的
admin //this is the user check
/home/admin
total 48
drwxr-xr-x 6 admin admin 4096 Dec 6 00:28 .
drwxr-xr-x 6 root root 4096 Nov 17 14:07 ..
drwxr-xr-x 3 admin admin 4096 Nov 17 14:00 .ansible
drwx------ 2 admin admin 4096 Nov 23 18:26 .appdata
-rw------- 1 admin admin 5002 Dec 6 17:47 .bash_history
-rw-r--r-- 1 admin admin 220 May 16 2017 .bash_logout
-rw-r--r-- 1 admin admin 3506 Jun 14 2019 .bashrc
-rw-r--r-- 1 admin admin 675 May 16 2017 .profile
drwx------ 4 admin admin 4096 Nov 23 18:26 .registry
drwx------ 2 admin admin 4096 Jun 21 2019 .ssh
-rw-r--r-- 1 admin admin 0 Dec 6 19:42 testFile.txt
-rw------- 1 admin admin 2236 Jun 21 2019 .viminfo
admin
如果我使用 sudo su -c 并删除 & 喜欢:
ssh -i $publicKey -t $var "sudo su -c ${script}; "
然后 whoami returns 用户作为 root 但工作目录仍然打印为 /home/admin而不是 /root 并且下一组命令仍然适用于管理员用户而不是根用户。所以管理员用户没有权限将构建移动到存档目录并安装构建。
使用 & 我想确保在后台完成进一步的步骤。 不确定如何继续进行。现在非常欢迎好的建议:)
当您单独使用 su
时,它会将您留在实际目录中,如果您使用 su -
,它会模拟 root 登录。
你应该写:su - root -c ${script};
"sudo su - & ${script}; "
扩展为:
sudo su - & whoami && pwd && ...
第一个 sudo su -
在后台 运行 。然后执行命令链。
sudo su -c ${script};
扩展为:
sudo su -c whoami && pwd && ...
所以首先sudo su - whoami
被执行,其中运行s whoami
作为root。然后如果这个命令成功,那么pwd
就会被执行。作为普通用户。
使用 ssh 正确传递命令以在远程站点上执行是非常困难的。使用 sudo su
越来越难做到这一点 - 命令将是 triple (或两次?)单词拆分 - 一次通过 ssh,然后通过 shell , 然后 shell 运行 sudo su
.
如果你不需要交互式交流,最好使用带有-s
shell选项的here文档,一些东西(未测试):
# DO NOT store commands to use in a variable.
# or if you do and you know what you are doing, properly quote it (printf "%q ") and run it via eval
script() {
set -euo pipefail
whoami
pwd
ls -la
whoami
mv "$buildVersion" "$buildPathToStore"
find "$buildPathToStore" | grep deb9
}
ssh ... "sudo bash -s" <<EOF
echo "Yay! anything here!"
echo "Note that here document delimiter is not quoted!"
$(
# safely import context to work with
# note how command substitution is executed on host side
declare -f script
# pass variables too!
declare -p buildVersion buildPathToStore buildPathToStore
)
script
EOF