bash 通过 SSH 远程运行脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12937634/
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-09-18 03:33:33  来源:igfitidea点击:

Run scripts remotely via SSH

linuxbashsshautologin

提问by Satish

I need to collect user information from 100 remote servers. We have public/private key infrastructure for authentication, and I have configured ssh-agentcommand to forward key, meaning i can login on any server without password prompt (auto login).

我需要从 100 个远程服务器收集用户信息。我们有用于身份验证的公钥/私钥基础设施,我已经配置ssh-agent了转发密钥的命令,这意味着我可以在没有密码提示的情况下登录任何服务器(自动登录)。

Now I want to run a script on all server to collect user information (how many user account we have on all servers).

现在我想在所有服务器上运行一个脚本来收集用户信息(我们在所有服务器上有多少用户帐户)。

This is my script to collect user info.

这是我收集用户信息的脚本。

#!/bin/bash
_l="/etc/login.defs"
_p="/etc/passwd"

## get mini UID limit ##
l=$(grep "^UID_MIN" $_l)

## get max UID limit ##
l1=$(grep "^UID_MAX" $_l)

awk -F':' -v "min=${l##UID_MIN}" -v "max=${l1##UID_MAX}" '{ if (  >= min &&  <= max  &&  != "/sbin/nologin" ) print 
$ ssh remote_machine ~/script.sh
}' "$_p"

I don't know how to run this script using ssh without interaction??

我不知道如何在没有交互的情况下使用 ssh 运行这个脚本?

采纳答案by Benjamin Bannier

Since you need to log into the remote machine there is AFAICT no way to do this "without ssh". However, sshaccepts a command to execute on the remote machine once logged in (instead of the shell it would start). So if you can save your script on the remote machine, e.g. as ~/script.sh, you can execute it without starting an interactive shell with

由于您需要登录远程计算机,因此 AFAICT 无法“没有 ssh”来执行此操作。但是,ssh一旦登录就接受在远程机器上执行的命令(而不是它会启动的 shell)。因此,如果您可以将脚本保存在远程计算机上,例如 as ~/script.sh,则可以在不启动交互式 shell 的情况下执行它

#!/bin/bash

servers=(wopr gerty mother)

fmt="%s\t%s\t%s\n"
printf "$fmt" "Host" "UIDs" "Highest"
printf "$fmt" "----" "----" "-------"

count='awk "END {print NR}" /etc/passwd' # avoids whitespace problems from `wc`
highest="awk -F: '$3>n&&$3<60000{n=$3} END{print n}' /etc/passwd"

for server in ${servers[@]}; do
    printf "$fmt" "$server" "$(ssh "$server" "$count")" "$(ssh "$server" "$highest")"
done

Once the script terminates the connection will automatically be closed (if you didn't configure that away purposely).

一旦脚本终止,连接将自动关闭(如果您没有故意配置它)。

回答by andrux

Sounds like something you can do using expect.

听起来像你可以用expect来做的事情。

http://linux.die.net/man/1/expect

http://linux.die.net/man/1/expect

Expect is a program that "talks" to other interactive programs according to a script. Following the script, Expect knows what can be expected from a program and what the correct response should be.

Expect 是一个根据脚本与其他交互式程序“对话”的程序。按照脚本,Expect 知道可以从程序中得到什么以及正确的响应应该是什么。

回答by ghoti

If you've got a key on each machine and can ssh remotehostfrom your monitoring host, you've got all that's required to collect the information you've asked for.

如果您在每台机器上都有一个密钥并且可以ssh remotehost从您的监控主机获得,那么您就拥有了收集您所要求的信息所需的一切。

$ ./doit.sh
Host    UIDs    Highest
----    ----    -------
wopr    40      2020
gerty   37      9001
mother  32      534

Results for me:

我的结果:

#!/usr/local/bin/bash

servers=(wopr gerty mother)

fmt="%s\t%s\t%s\n"
printf "$fmt" "Host" "UIDs" "Highest"
printf "$fmt" "----" "----" "-------"

gather="awk -F: '$3>n&&$3<60000{n=$3} END{print NR,n}' /etc/passwd"

for server in ${servers[@]}; do
    read count highest < <(ssh "$server" "$gather")
    printf "$fmt" "$server" "$count" "$highest"
done

Note that this makes TWO ssh connections to each server to collect each datum. If you'd like to do this a little more efficiently, you can bundle the information into a single, slightly more complex collection script:

请注意,这会与每个服务器建立两个 ssh 连接以收集每个数据。如果您想更有效地执行此操作,可以将信息捆绑到一个稍微复杂的收集脚本中:

#!/usr/bin/expect
set timeout 30
spawn ssh -p ssh_port -l ssh_username ssh_server_host
expect "password:" 
send "your_passwd\r"
interact

(Identical results.)

(相同的结果。)

回答by c4f4t0r

ssh remoteserver.example /bin/bash < localscript.bash

ssh remoteserver.example /bin/bash < localscript.bash

回答by fayhot

maybe you'd like to try the expect command as following

也许你想尝试如下的expect命令

login=user
IP=127.0.0.1
password='your_password'

expect_sh=$(expect -c "
spawn ssh $login@$IP
expect \"password:\"
send \"$password\r\"
expect \"#\"
send \"./$remote_side_script\r\"
expect \"#\"
send \"cd /lib\r\"
expect \"#\"
send \"cat file_name\r\" 
expect \"#\"
send \"exit\r\"
")

echo "$expect_sh"

the expect command will catch the "password:" and then auto fill the passwd your send by above.

期望命令将捕获“密码:”,然后自动填写您在上面发送的密码。

Remember that replace the ssh_port, ssh_username, ssh_server_host and your_passwd with your own configure

请记住,将 ssh_port、ssh_username、ssh_server_host 和 your_passwd 替换为您自己的配置

回答by sampson-chen

(Note: the "proper" way to authenticate without manually entering in password is to use SSH keys. Storing password in plaintext even in your local scripts is a potential security vulnerability)

(注意:无需手动输入密码进行身份验证的“正确”方法是使用 SSH 密钥。即使在本地脚本中以明文形式存储密码也是一个潜在的安全漏洞)

You can run expect as part of your bash script. Here's a quick example that you can hack into your existing script:

您可以将 expect 作为 bash 脚本的一部分运行。这是一个快速示例,您可以使用它来破解现有脚本:

$ sudo apt-get install putty-tools

You can also use pscp to copy files back and forth as part of a script so you don't need to manually supply the password as part of the interaction:

您还可以使用 pscp 作为脚本的一部分来回复制文件,因此您无需在交互过程中手动提供密码:

Install putty-tools:

安装腻子工具:

pscp -scp -pw $password file_to_copy $login@$IP:$dest_dir

Using pscp in your script:

在脚本中使用 pscp:

##代码##