Run scripts remotely via SSH

2019-05-11 15:38发布

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

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 ( $3 >= min && $3 <= max  && $7 != "/sbin/nologin" ) print $0 }' "$_p"

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

6条回答
Anthone
2楼-- · 2019-05-11 16:19

Since you need to log into the remote machine there is AFAICT no way to do this "without ssh". However, ssh accepts 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

$ ssh remote_machine ~/script.sh

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

查看更多
来,给爷笑一个
3楼-- · 2019-05-11 16:28

(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)

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

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"

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:

Install putty-tools:

$ sudo apt-get install putty-tools

Using pscp in your script:

pscp -scp -pw $password file_to_copy $login@$IP:$dest_dir
查看更多
我想做一个坏孩纸
4楼-- · 2019-05-11 16:31

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

查看更多
成全新的幸福
5楼-- · 2019-05-11 16:31

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

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

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

查看更多
姐就是有狂的资本
6楼-- · 2019-05-11 16:35

Sounds like something you can do using 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.

查看更多
家丑人穷心不美
7楼-- · 2019-05-11 16:37

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

#!/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

Results for me:

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

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:

#!/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

(Identical results.)

查看更多
登录 后发表回答