How can i run bash on a remote linux server - linux

Lets say i have two servers on the same network:
db-test-1
db-test-2
On db-test-1, how can i run a bash command that executes on db-test-2? For example, on db-test-1, run a command that checks if a program is running on the remote server, e.g,
ps -ef |grep consul
I have to use the server name, not IP by the way.

With ssh keys:
On db-test1: generate a pair of ssh keys (ssh-keygen)
Append or copy .ssh/id_rsa.pub of db-test1 to .ssh/authorized_keys
on db-test1: ssh db-test2 ps -ef | grep consul
The first connection you will be ask if you trust the remote host. You can remote this by adding: StrictHostKeyChecking no in .ssh/config

Related

ssh "port 22: no route to host" error in bash script

I wrote a scipt to execute a couple of ssh remote comands relating to apache storm. When I execute the script it says:
ssh: connect to host XXX.XXX.XXX.XXX port 22: No route to host
ssh: connect to host XXX.XXX.XXX.XXX port 22: No route to host
ssh: connect to host XXX.XXX.XXX.XXX port 22: No route to host
ssh: connect to host XXX.XXX.XXX.XXX port 22: Connection refused
If I execute the commands manually it works out well and I can ping the machine. So that there has to be something wrong with this code:
while [ $i -le $numVM ]
do
if [ $i -eq 1 ];then
ssh -i file root#IP1 './zookeeper-3.4.6/bin/zkServer.sh start'
else
ssh -i file root#IP2 'sed -i '"'"'s/#\ storm.zookeeper.servers.*/storm.zookeeper.servers:/'"'"' /root/apache-storm-0.9.3/conf/storm.yaml'
ssh -i file root#IP2 'sed -i '"'"'0,/^#[[:space:]]*-[[:space:]]*\"server1\".*/s//" - \"'${IParray[1]}'\""/'"'"' /root/apache-storm-0.9.3/conf/storm.yaml'
ssh -i file root#IP2 'sed -i '"'"'s/#\ nimbus.host:.*/"nimbus.host: \"'${IParray[2]}'\""/'"'"' /root/apache-storm-0.9.3/conf/storm.yaml'
ssh -i file root#IP2 './zookeeper-3.4.6/bin/zkCli.sh -server ${IParray[1]} &'
sleep 10
ssh -i file root#IP2 './apache-storm-0.9.3/bin/storm nimbus &' &
sleep 10
ssh -i file root#IP2 './apache-storm-0.9.3/bin/storm ui &' &
sleep 10
ssh -i file root#IP2 './apache-storm-0.9.3/bin/storm supervisor &' &
fi
((i++))
done
I'm starting several processes on 2 virtual machines that are deployed from the same image, so that they are identical in general. The confusing part is, that the first ssh command (zkServer.sh start) is working well but if I the script tries to execute the three "sed"-ssh-commands I get the error message above. But then the last four ssh-commands are working out well again. That does not make any sense to me...
Several things I can think of:
Most sshd daemons won't allow root access. Heck, many versions of Unix/Linux no longer allow root login. If you need root access, you need to use sudo.
The sshd daemon on the remote machine isn't running. Although rare, some sites may never had it setup, or purposefully shut it off as a security issue.
Your ssh commands themselves are incorrect.
Instead of executing the ssh commands in your shell script, modify the shell script just to print out what you're attempting to execute. Then, see if you can execute the command outside of the shell script. This way you can determine whether the problem is the shell script, or the problem is with the ssh command itself.
If your ssh commands don't work outside from the command line, you can then simplify them and see if you can determine what the issue could be. You have ssh -i file root#IP2. Is this suppose to be ssh -i $file root#$IP2? (i.e., you're missing the leading sigil).
$ ssh -i file root#$IP2 ls # Can't get simpler than this...
$ ssh -i file root#IPS # See if you can remotely log on...
$ ssh root#IP2 # Try it without an 'identity file'
$ ssh bob#IP2 # Try it as a user other than 'root'
$ telnet IP2 22 # Is port 22 even open on the remote machine?
If these don't work, then you have some very basic issue with the setup of your remote machine's sshd command.

get the process name from remote machine

How do I get the name of a process from a remote machine without ssh.
I have to get the name of the process without doing ssh or any other such utility.
Thanks in advance.
You can do it very quickly using netcat nc
On the remote server run this command:
while $(true); do ps -eaf | nc -l 1234; done
This uses netcat to send the output of ps to port 1234. It is in a loop so that it will work more than once.
Then from your local you just have to run this command:
nc my_server 1234
And you will get a list of all the processes. If you don't have nc on the client you can just use telnet:
telnet my_server 1234

some commands not wroking on remote servers through ssh (shell)

I have to run some userdefined commands on remote servers. So I do the following. It works for many commands such as crontab -l, ls, date +%s, etc... However, it doesn't work for ip addr
When I actually ssh INSIDE those server ip addr works fine. But when I execute it using ssh it doesnt.
This is how I execute it.
$ sshpass -p myPassword ssh -q root#127.0.0.1 'ip addr' > $PWD/tmp
$ cat $PWD/tmp
Again, this works for any commands I've tried so far except ip addr.
For ip addr it gives the following output
bash: ip: command not found
So i was wondering why and if there's anything wrong I'm doing....
Also, please don't sugges to use rsync or any other nondefault linux command since the environment I work in does not have them nor do I have the permission to install.
Thank you in advance
This is caused because a non-interactive ssh session does not source your login profile, which amongst other things is setting your PATH variable.
The default path does not contain /sbin, which is the usual location of the ip command.

write a shell script to ssh to a remote machine and execute commands

I have two questions:
There are multiple remote linux machines, and I need to write a shell script which will execute the same set of commands in each machine. (Including some sudo operations). How can this be done using shell scripting?
When ssh'ing to the remote machine, how to handle when it prompts for RSA fingerprint authentication.
The remote machines are VMs created on the run and I just have their IPs. So, I cant place a script file beforehand in those machines and execute them from my machine.
There are multiple remote linux machines, and I need to write a shell script which will execute the same set of commands in each machine. (Including some sudo operations). How can this be done using shell scripting?
You can do this with ssh, for example:
#!/bin/bash
USERNAME=someUser
HOSTS="host1 host2 host3"
SCRIPT="pwd; ls"
for HOSTNAME in ${HOSTS} ; do
ssh -l ${USERNAME} ${HOSTNAME} "${SCRIPT}"
done
When ssh'ing to the remote machine, how to handle when it prompts for RSA fingerprint authentication.
You can add the StrictHostKeyChecking=no option to ssh:
ssh -o StrictHostKeyChecking=no -l username hostname "pwd; ls"
This will disable the host key check and automatically add the host key to the list of known hosts. If you do not want to have the host added to the known hosts file, add the option -o UserKnownHostsFile=/dev/null.
Note that this disables certain security checks, for example protection against man-in-the-middle attack. It should therefore not be applied in a security sensitive environment.
Install sshpass using, apt-get install sshpass then edit the script and put your linux machines IPs, usernames and password in respective order. After that run that script. Thats it ! This script will install VLC in all systems.
#!/bin/bash
SCRIPT="cd Desktop; pwd; echo -e 'PASSWORD' | sudo -S apt-get install vlc"
HOSTS=("192.168.1.121" "192.168.1.122" "192.168.1.123")
USERNAMES=("username1" "username2" "username3")
PASSWORDS=("password1" "password2" "password3")
for i in ${!HOSTS[*]} ; do
echo ${HOSTS[i]}
SCR=${SCRIPT/PASSWORD/${PASSWORDS[i]}}
sshpass -p ${PASSWORDS[i]} ssh -l ${USERNAMES[i]} ${HOSTS[i]} "${SCR}"
done
This work for me.
Syntax : ssh -i pemfile.pem user_name#ip_address 'command_1 ; command 2; command 3'
#! /bin/bash
echo "########### connecting to server and run commands in sequence ###########"
ssh -i ~/.ssh/ec2_instance.pem ubuntu#ip_address 'touch a.txt; touch b.txt; sudo systemctl status tomcat.service'
There are a number of ways to handle this.
My favorite way is to install http://pamsshagentauth.sourceforge.net/ on the remote systems and also your own public key. (Figure out a way to get these installed on the VM, somehow you got an entire Unix system installed, what's a couple more files?)
With your ssh agent forwarded, you can now log in to every system without a password.
And even better, that pam module will authenticate for sudo with your ssh key pair so you can run with root (or any other user's) rights as needed.
You don't need to worry about the host key interaction. If the input is not a terminal then ssh will just limit your ability to forward agents and authenticate with passwords.
You should also look into packages like Capistrano. Definitely look around that site; it has an introduction to remote scripting.
Individual script lines might look something like this:
ssh remote-system-name command arguments ... # so, for exmaple,
ssh target.mycorp.net sudo puppet apply
The accepted answer sshes to machines sequentially. In case you want to ssh to multiple machines and run some long-running commands like scp concurrently on them, run the ssh command as a background process.
#!/bin/bash
username="user"
servers=("srv-001" "srv-002" "srv-002" "srv-003");
script="pwd;"
for s in "${servers[#]}"; do
echo "sshing ${username}#${s} to run ${script}"
(ssh ${username}#${s} ${script})& # Run in background
done
wait # If removed, you can run some other script here
If you are able to write Perl code, then you should consider using Net::OpenSSH::Parallel.
You would be able to describe the actions that have to be run in every host in a declarative manner and the module will take care of all the scary details. Running commands through sudo is also supported.
For this kind of tasks, I repeatedly use Ansible which allows to duplicate coherently bash scripts in several containets or VM. Ansible (more precisely Red Hat) now has an additional web interface AWX which is the open-source edition of their commercial Tower.
Ansible: https://www.ansible.com/
AWX:https://github.com/ansible/awx
Ansible Tower: commercial product, you will probably fist explore the free open-source AWX, rather than the 15days free-trail of Tower
There is are multiple ways to execute the commands or script in the multiple remote Linux machines.
One simple & easiest way is via pssh (parallel ssh program)
pssh: is a program for executing ssh in parallel on a number of hosts. It provides features such as sending input to all of the processes, passing a password to ssh, saving the output to files, and timing out.
Example & Usage:
Connect to host1 and host2, and print "hello, world" from each:
pssh -i -H "host1 host2" echo "hello, world"
Run commands via a script on multiple servers:
pssh -h hosts.txt -P -I<./commands.sh
Usage & run a command without checking or saving host keys:
pssh -h hostname_ip.txt -x '-q -o StrictHostKeyChecking=no -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes' -i 'uptime; hostname -f'
If the file hosts.txt has a large number of entries, say 100, then the parallelism option may also be set to 100 to ensure that the commands are run concurrently:
pssh -i -h hosts.txt -p 100 -t 0 sleep 10000
Options:
-I: Read input and sends to each ssh process.
-P: Tells pssh to display output as it arrives.
-h: Reads the host's file.
-H : [user#]host[:port] for single-host.
-i: Display standard output and standard error as each host completes
-x args: Passes extra SSH command-line arguments
-o option: Can be used to give options in the format used in the configuration file.(/etc/ssh/ssh_config) (~/.ssh/config)
-p parallelism: Use the given number as the maximum number of concurrent connections
-q Quiet mode: Causes most warning and diagnostic messages to be suppressed.
-t: Make connections time out after the given number of seconds. 0 means pssh will not timeout any connections
When ssh'ing to the remote machine, how to handle when it prompts for
RSA fingerprint authentication.
Disable the StrictHostKeyChecking to handle the RSA authentication prompt.
-o StrictHostKeyChecking=no
Source: man pssh
This worked for me. I made a function. Put this in your shell script:
sshcmd(){
ssh $1#$2 $3
}
sshcmd USER HOST COMMAND
If you have multiple machines that you want to do the same command on you would repeat that line with a semi colon. For example, if you have two machines you would do this:
sshcmd USER HOST COMMAND ; sshcmd USER HOST COMMAND
Replace USER with the user of the computer. Replace HOST with the name of the computer. Replace COMMAND with the command you want to do on the computer.
Hope this helps!
You can follow this approach :
Connect to remote machine using Expect Script. If your machine doesn't support expect you can download the same. Writing Expect script is very easy (google to get help on this)
Put all the action which needs to be performed on remote server in a shell script.
Invoke remote shell script from expect script once login is successful.

linux execute command remotely

how do I execute command/script on a remote linux box?
say I want to do service tomcat start on box b from box a.
I guess ssh is the best secured way for this, for example :
ssh -OPTIONS -p SSH_PORT user#remote_server "remote_command1; remote_command2; remote_script.sh"
where the OPTIONS have to be deployed according to your specific needs (for example, binding to ipv4 only) and your remote command could be starting your tomcat daemon.
Note:
If you do not want to be prompt at every ssh run, please also have a look to ssh-agent, and optionally to keychain if your system allows it. Key is... to understand the ssh keys exchange process. Please take a careful look to ssh_config (i.e. the ssh client config file) and sshd_config (i.e. the ssh server config file). Configuration filenames depend on your system, anyway you'll find them somewhere like /etc/sshd_config. Ideally, pls do not run ssh as root obviously but as a specific user on both sides, servers and client.
Some extra docs over the source project main pages :
ssh and ssh-agent
man ssh
http://www.snailbook.com/index.html
https://help.ubuntu.com/community/SSH/OpenSSH/Configuring
keychain
http://www.gentoo.org/doc/en/keychain-guide.xml
an older tuto in French (by myself :-) but might be useful too :
http://hornetbzz.developpez.com/tutoriels/debian/ssh/keychain/
ssh user#machine 'bash -s' < local_script.sh
or you can just
ssh user#machine "remote command to run"
If you don't want to deal with security and want to make it as exposed (aka "convenient") as possible for short term, and|or don't have ssh/telnet or key generation on all your hosts, you can can hack a one-liner together with netcat. Write a command to your target computer's port over the network and it will run it. Then you can block access to that port to a few "trusted" users or wrap it in a script that only allows certain commands to run. And use a low privilege user.
on the server
mkfifo /tmp/netfifo; nc -lk 4201 0</tmp/netfifo | bash -e &>/tmp/netfifo
This one liner reads whatever string you send into that port and pipes it into bash to be executed. stderr & stdout are dumped back into netfifo and sent back to the connecting host via nc.
on the client
To run a command remotely:
echo "ls" | nc HOST 4201

Resources