使用 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