Execute a remote script on a local server in Linux using ssh - linux

I have a script called "test" on a remote server's home folder that contains the following lines:
#!/bin/bash
tengbe=`ifconfig | grep -B1 192.168 | awk 'NR==1 { print $1 }' | sed 's/://g'`
Basically, it just stores the name of the interface of the local server into a variable once the script is called. When I ssh into the remote server to call the script, I get an error:
ssh remoteserver-IP './test'
./test: line 3: ifconfig: command not found
What might be wrong with my script? I have seen various answers that does not offer a solution to my issue.

Try:
$ ssh remotehost ifconfig
bash: ifconfig: command not found
ifconfig isn't in your PATH on the remote host. You can prove it with:
$ which ifconfig
/sbin/ifconfig
$ ssh remotehost 'echo $PATH'
(returns lots of dirs, none of which is /sbin)
To get around this either specify the full path to ifconfig:
$ ssh remotehost /sbin/ifconfig
... or configure $PATH before calling it:
$ ssh remotehost 'PATH=$PATH:/sbin ifconfig'
... or edit $HOME/.bashrc (or alternatives -- read about your shell's initialisation process) to add /sbin to $PATH all the time.
For security, in a script it's usually better to specify absolute paths, maybe via variables. So in your script:
#!/bin/bash
IFCONFIG=/sbin/ifconfig
tengbe=$(${IFCONFIG} | grep -B1 192.168 | awk 'NR==1 { print $1 }' | sed 's/://g')
Note, I've replaced your backticks with $() - this isn't required, but it's a good habit to adopt - What is the benefit of using $() instead of backticks in shell scripts?

Related

Bash for loops on a remote server

I am attempting to run multiple commands via a bash script on a remote server. specifically, the for loop to be run on the remote server is giving me issues. I suspect it is because I don't know how to properly escape characters or use $().
Below is the code.
ssh (user)#(server) <<EOF
sudo su - (username)
whoami
'for e in $(`ls -lrt /usr/jboss/jbosseap | awk '{print $9}' | grep multichannel`);
do
echo "$e";
done'
Removing user and server names for obvious reasons. Just concentrate on the for loop. when I run that for loop command line (without the $()) its works fine. Just not sure how to nest it in a remote call.
Thanks very much for any and all help!
If you've got a complex script that you're trying to run over ssh you're going to be better off putting that script in a file and piping that file into ssh like:
cat remote_script.sh | ssh user#host
or:
cat remote_script.sh | ssh user#host sudo -u username
And now you don't have to worry about N levels of escaping.
You can run it as below .
here file "list " includes your list of nodes and script should be present in all nodes
for i in $(cat list ) ;do ssh -o StrictHostKeyChecking=no $i "/path/your_script" ;done

Shell script to compare remote directories

I have a shell script that I am using to compare directory contents. The script has to ssh to different servers to get a directory listing. When I run the script below, I am getting the contents of the server that I am logged into's /tmp directory listing and not that of the servers I am trying to ssh to. Could you please tell me what I am doing wrong?
The config file used in the script is as follows (called config.txt):
server1,server2,/tmp
The script is as follows
#!/bin/sh
CONFIGFILE="config.txt"
IFS=","
while read a b c
do
SERVER1=$a
SERVER2=$b
COMPDIR=$c
`ssh user#$SERVER1 'ls -l $COMPDIR'`| sed -n '1!p' >> server1.txt
`ssh user#$SERVER2 'ls -l $COMPDIR'`| sed -n '1!p' >> server2.txt
done < $CONFIGFILE
When I look at the outputs of server1.txt and server2.txt, they are both exactly the same - having the contents of /tmp of the server the script is running on (not server1 or 2). Doing the ssh +dir listing on command line works just fine. I am also getting the error "Pseudo-terminal will not be allocated because stdin is not a terminal". Adding the -t -t to the ssh command isnt helping either
Thank you
I have the back ticks in order to execute the command.
Backticks are not needed to execute a command - they are used to expand the standard output of the command into the command line. Certainly you don't want the output of your ssh commands to be interpreted as commands. Thus, it should work fine without the backticks:
ssh user#$SERVER1 "ls -l $COMPDIR" | sed -n '1!p' >>server1.txt
ssh user#$SERVER2 "ls -l $COMPDIR" | sed -n '1!p' >>server2.txt
(provided that double quotes to allow expansion of $COMPDIR are used).
first you need to generate keys to login to remote without keys
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub remote-host
then try to ssh without pass
ssh remote-host
then try to invoke in your script but first make sanity check
var1=$(ssh remote-host) die "Cannot connect to remote host" unless $var1;

Bash cat on the last created remote file [duplicate]

This question already has answers here:
Shell Script error: "head: invalid trailing option -- 1"
(3 answers)
Closed 8 years ago.
I am trying to recover the content of the last created file on a remote server.
When connected to the remote server I do this:
cat `ls -t /mypath/*.csv | head -1`
CMD="cat `ls -t /mypath/*.txt | head -1`"
But when I try to use the same command:
ssh#XX.XX.XX.XX $CMD
I get an error: ls cannot access /mypath/*.csv No such file or directory.
The ` is forcing to execute the ls on the local system on not the remote.
Is there another way?
Thank you
Your command is failing is because the backticks in $CMD are expanded locally when you create the variable, rather than being expanded on the remote side. So ssh#XX.XX.XX.XX $CMD is actually going to look something like ssh#XX.XX.XX.XX "cat /mypath/local_file" (and local_file may not exists on the remote host, and is probably not the file you want).
You can prevent this local expansion by providing the command directly to ssh.
ssh user#host 'cat /mypath/$(ls -t /mypath/*.txt | head -1)'
ls returns the pathname relative to the directory so you will also need to include the path of the base directory /mypath/ in your cat invocation. To avoid this hardcoding pass the -d flag to ls.
ssh user#host 'cat $(ls -dt /mypath/*.txt | head -1)'

SSH find and replace string in a list of filenames

We have a repository of about 3000 MP3 files. Many of these files have our old domain name within their name.
For example: somesong_oldDomainName.mp3
I need to SSH into the site, find all instances of those files and rename them with the new domain name.
Example: somesong_NEWDomainName.mp3
I know the basic SSH commands but not something advanced like this.
Pretty sure it'll be a combination of multiple commands.
Assuming you get an interactive shell when you ssh into your linux server, this might be a possible way:
ssh user#machine-name-or-ip
then you will get some sort of terminal like
user#machine-name:~$
where you enter the commands to execute on that remote machine.
As mentioned in the comments, the answer here might just fit very well:
Bash: Rename small part of multiple files in middle of name
user#machine-name:~$ for i in *.mp3; do mv "$i" "$(echo "$i" | sed 's/_oldDomainName/_NEWDomainName/g')"; done
This assumes, your current directory is the one with all the MP3 files in it.
If you dont want interactivly operate on your files, e.g. because they change very often and you want a script to perform this action, SSH can also execute a command and/or shell script remotely.
To pass the command directly with the SSH call:
SSH error when executing a remote command: "stdin: is not a tty"
To pipe a local shell script into the SSH connection: How to use SSH to run a shell script on a remote machine?
Run a remote shell script via SSH: how to run a script file remotely using ssh
Edit:
Assume you are connected via SSH to your remote machine and have somewhat similar versions of bash and sed, it should work like this:
$ ls
bar_chosefil.mp3 boo_chosefil.mp3 foo_chosefil.mp3
$ for i in *.mp3; do mv $i $(echo $i | sed 's/chosefil/tamasha/g'); done
$ ls
bar_tamasha.mp3 boo_tamasha.mp3 foo_tamasha.mp3
Versions involved:
bash: 4.2.25
sed: 4.2.1
mv: 8.13
Edit 2:
Updated the command to work with blanks in filenames
$ ls
asd chosefil.mp3 bar_chosefil.mp3 boo_chosefil.mp3 foo_chosefil.mp3
$ for i in *.mp3; do mv "$i" "$(echo "$i" | sed 's/chosefil/tamasha/g')"; done
$ ls
asd tamasha.mp3 bar_tamasha.mp3 boo_tamasha.mp3 foo_tamasha.mp3

find files on remote machine

Hi i am trying to execute the following command on a remote machine how do i do this
ssh login.com find /nfs/repo/ -name ".user_repo.log" | \
xargs cat | awk '{$NF=""; print $0}' | \
sed "1i Owner RepoName CreatedDate" | column -t
I get the following error message
cat: /nfs/repo/new1/info/.user_repo.log: No such file or directory
cat: /nfs/repo/new2/info/.user_repo.log: No such file or directory
cat command is trying to find file on the local system while these files are present on the remote machine.How do i handle this
If you do:
ssh host command1 | command2
Then the shell will break at the pipe, so you'll get "ssh host command1" run as one command (i.e. remotely), and then "command2" run as another command (i.e., locally.) You can force all the commands to run remotely by enclosing in quotes:
ssh host "command1 | command2"
Note, since you already have quotes in the command, you might have to get creative with escaping.
Or, you might put all those commands in a short shell script and then just run the script:
ssh host myscript.sh

Resources