Linux 如何编写 bash shell 脚本以通过 ssh 连接到远程机器并更改用户并导出环境变量并执行其他命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11005396/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 06:49:10  来源:igfitidea点击:

how to write a bash shell script to ssh to remote machine and change user and export a env variable and do other commands

linuxbashsshperforceredhat

提问by Peiti Li

I have a webservice that runs on multiple different remote redhat machines. Whenever I want to update the service I will sync down the new webservice source code written in perl from a version control depot(I use perforce) and restart the service using that new synced down perl code. I think it is too boring to log to remote machines one by one and do that series of commands to restart the service one by one manully. So I wrote a bash script update.sh like below in order to "do it one time one place, update all machines". I will run this shell script in my local machine. But it seems that it won't work. It only execute the first command "sudo -u webservice_username -i" as I can tell from the command line in my local machine. (The code below only shows how it will update one of the remote webservice. The "export P4USER=myname" is for usage of perforce client)

我有一个在多个不同的远程 redhat 机器上运行的 web 服务。每当我想更新服务时,我都会同步从版本控制库(我使用 perforce)用 perl 编写的新 webservice 源代码,并使用新同步的 perl 代码重新启动服务。我觉得一个一个登录到远程机器上然后执行那一系列的命令来手动重启服务太无聊了。所以我写了一个像下面这样的 bash 脚本 update.sh 以“一次一次地完成,更新所有机器”。我将在我的本地机器上运行这个 shell 脚本。但似乎行不通。它只执行第一个命令“sudo -u webservice_username -i”,我可以从本地机器的命令行中得知。(下面的代码仅显示它将如何更新远程网络服务之一。“

#!/bin/sh
    ssh myname@remotehost1 'sudo -u webservice_username -i ; export P4USER=myname; cd dir ; p4 sync ; cd bin ; ./prog --domain=config_file restart ; tail -f ../logs/service.log'

Why I know the only first command is executed? Well because after I input the password for the ssh on my local machine, it shows:

为什么我知道唯一的第一个命令被执行?好吧,因为在我在本地机器上输入 ssh 的密码后,它显示:

Your environment has been modified. Please check /tmp/webservice.env.

And it just gets stuck there. I mean no return.

它只是卡在那里。我的意思是没有回报。

As suggested by a commentor, I added "-t" for ssh

正如评论者所建议的,我为 ssh 添加了“-t”

#!/bin/sh
        ssh -t myname@remotehost1 'sudo -u webservice_username -i ; export P4USER=myname; cd dir ; p4 sync ; cd bin ; ./prog --domain=config_file restart ; tail -f ../logs/service.log'

This would let the local commandline return. But it seems weird, it cannot cd to that "dir", it says "cd:dir: No such file or directory" it also says "p4: command not found". So it looks like the sudo -u command executes with no effect and the export command has either not executed or excuted with no effect.
A detailed local log file is like below:

这将使本地命令行返回。但看起来很奇怪,它不能 cd 到那个“目录”,它说“cd:dir:没有这样的文件或目录”它还说“p4:找不到命令”。所以看起来 sudo -u 命令执行没有效果,导出命令要么没有执行,要么没有执行。
详细的本地日志文件如下所示:

Your environment has been modified. Please check /tmp/dir/.env.
bash: line 0: cd: dir: No such file or directory
bash: p4: command not found
bash: line 0: cd: bin: No such file or directory
bash: ./prog: No such file or directory
tail: cannot open `../logs/service.log' for reading: No such file or directory
tail: no files remaining

回答by bta

Instead of connecting via ssh and then immediately changing users, can you not use something like ssh -t webservice_username@remotehost1to connect with the desired username to begin with? That would avoid needing to sudoaltogether.

除了通过 ssh 连接然后立即更改用户之外,您是否可以不使用类似的ssh -t webservice_username@remotehost1方式连接所需的用户名?这将sudo完全避免需要。

If that isn't a possibility, try wrapping up all of the commands that you want to run in a shell script and store it on the remote machine. If you can get your task working from a script, then your sshcall becomes much simpler and should encounter fewer problems:

如果这不可能,请尝试将要在 shell 脚本中运行的所有命令打包并将其存储在远程计算机上。如果您可以从脚本开始您的任务,那么您的ssh调用就会变得更加简单,并且应该会遇到更少的问题:

ssh myname@remotehost1 '/path/to/script'

For easily updating this script, you can write a short script for your local machine that uploads the most recent version via scpand then uses sshto invoke it.

为了轻松更新此脚本,您可以为本地机器编写一个简短的脚本,通过它上传最新版本scp,然后使用ssh它来调用它。

回答by Nik

Note that when you run:

请注意,当您运行时:

#!/bin/sh
    ssh myname@remotehost1 'sudo -u webservice_username -i ; export P4USER=myname; cd dir ; p4 sync ; cd bin ; ./prog --domain=config_file restart ; tail -f ../logs/service.log'

Your ssh session runs sudo -u webservice_username -iwaits for it to exit and then runs the rest of the commands; it does not execute sudoand then run the commands following. This has to do with the context in which you're running the series of commands. All the commands get executed in the shell of myname@remotehost1and all sudo -u webservice_username - iis starts a shell for webservice_username and doesn't actually run any commands.

你的 ssh 会话运行sudo -u webservice_username -i等待它退出,然后运行其余的命令;它不会执行sudo,然后运行以下命令。这与您运行一系列命令的上下文有关。所有命令都在 shell 中执行,myname@remotehost1并且所有命令都sudo -u webservice_username - i为 webservice_username 启动一个 shell,并且实际上并不运行任何命令。

Really the best solution here is like bta said; write a script and then rsync/scp it to the destination and then run that using sudo.

真的这里最好的解决方案就像 bta 说的;编写一个脚本,然后将它 rsync/scp 到目的地,然后使用sudo.

回答by tomriddle_1234

export command simply not working with ssh like this, what you want to do is remote modify ~/.bashrc and it will source itself each time u do ssh login.

export 命令根本不能像这样使用 ssh,您想要做的是远程修改 ~/.bashrc 并且每次您进行 ssh 登录时它都会自行获取源代码。