Shell script to grep logs on different host and write the grepped output to a file on Host 1 - shell

Shell script needs to
ssh to Host2 from Host1
cd /test/test1/log
grep logs.txt for string error
write the grepped output to a file
and move that file to Host1

This can be accomplished by specifying the -f option to ssh:
ssh user#host -f 'echo "this is a logfile">logfile.txt'
ssh user#host -f 'grep logfile logfile.txt' > locallogfile.txt
cat locallogfile.txt
An example using a different directory and cd changing directories to it:
ssh user#host -f 'mkdir -p foo/bar'
ssh user#host -f 'cd foo/bar ; echo "this is a logfile">logfile.txt'
ssh user#host -f 'cd foo/bar ; echo "this is a logfile">logfile.txt'
ssh user#host -f 'cd foo/bar ; grep logfile logfile.txt' > locallogfile.txt
cat locallogfile.txt

Related

Execute multiple commands on remote server using bash

I want to execute cd and scp commands on a remote server which have to be logged in with a different sudo user. Below code snippet asks for the password(echos on screen) for my user but hangs there. It doesn't execute cd
#!/bin/bash
server=myserver.com
ssh $server 'sudo -S -u <user> -i; cd dir1/dir2/; scp file1 user#local-sever'
The issue is that you have a semi colon before cd and so sudo has no command to execute. Remove the ; and it should work:
ssh $server 'sudo -S -u <user> -i scp dir1/dir2/file1 user#local-sever'
There are several ways to address this, but most boil down to wrapping up the commands into a set of instructions. Raman's solution is good since it handles the issue by using full paths, but sometimes that isn't an option. Here's another take -
Assuming your command list can afford the quotes, I like here-strings.
ssh -t sa-nextgen-jenkins.eng.rr.com <<< "
echo 'set -x; cd /tmp; whoami; touch foo; ls -l foo; rm -f foo;'|sudo -iSu user
"
If you need the quotes, try a here-doc.
ssh -t sa-nextgen-jenkins.eng.rr.com <<END
echo 'set -x; echo "$RANDOM"; cd /tmp; whoami; touch foo; ls -l foo; rm -f foo;'|sudo -iSu $user
END
You can also write a small script that has arbitrarily complex commands and scp it over, then use a remote ssh call to execute it as the relevant user.

Weird output observed on executing ssh commands remotely over ProxyCommand

Team, I have two steps to perform:
SCP a shell script file to remote ubuntu linux machine
Execute this uploaded file on remote ubuntu linux machine over SSH session using PROXYCommand because I have bastion server in front.
Code:
scp -i /home/dtlu/.ssh/key.key -o "ProxyCommand ssh -i /home/dtlu/.ssh/key.key lab#api.dev.test.com -W %h:%p" /home/dtlu/backup/test.sh lab#$k8s_node_ip:/tmp/
ssh -o StrictHostKeyChecking=no -i /home/dtlu/.ssh/key.key -o 'ProxyCommand ssh -i /home/dtlu/.ssh/key.key -W %h:%p lab#api.dev.test.com' lab#$k8s_node_ip "uname -a; date;echo "Dummy123!" | sudo -S bash -c 'echo 127.0.1.1 \`hostname\` >> /etc/hosts'; cd /tmp; pwd; systemctl status cachefilesd | grep Active; ls -ltr /tmp/test.sh; echo "Dummy123!" | sudo -Sv && bash -s < test.sh"
Both calls above are working fine. I am able to upload test.sh and also its running but what is bothering me is during the process am observe weird output being thrown out.
output:
/tmp. <<< expected
[sudo] password for lab: Showing one
Sent message type=method_call sender=n/a destination=org.freedesktop.DBus object=/org/freedesktop/DBus interface=org.freedesktop.DBus member=Hello cookie=1 reply_cookie=0 error=n/a
Root directory /run/log/journal added.
Considering /run/log/journal/df22e14b1f83428292fe17f518feaebb.
Directory /run/log/journal/df22e14b1f83428292fe17f518feaebb added.
File /run/log/journal/df22e14b1f83428292fe17f518feaebb/system.journal added.
So, I don't want /run/log/hournal and other lines which don't correspond to my command in sh.
Consider adding -q to the scp and ssh commands to reduce the output they might produce. You can also redirect stderr and stdout to /dev/null as appropriate.
For example:
{
scp -q -i /home/dtlu/.ssh/key.key -o "ProxyCommand ssh -i /home/dtlu/.ssh/key.key lab#api.dev.test.com -W %h:%p" /home/dtlu/backup/test.sh lab#$k8s_node_ip:/tmp/
ssh -q -o StrictHostKeyChecking=no -i /home/dtlu/.ssh/key.key -o 'ProxyCommand ssh -i /home/dtlu/.ssh/key.key -W %h:%p lab#api.dev.test.com' lab#$k8s_node_ip "uname -a; date;echo "Dummy123!" | sudo -S bash -c 'echo 127.0.1.1 \`hostname\` >> /etc/hosts'; cd /tmp; pwd; systemctl status cachefilesd | grep Active; ls -ltr /tmp/test.sh; echo "Dummy123!" | sudo -Sv && bash -s < test.sh"
} >&/dev/null

Passing Config Content to SSH Command

Normally we pass config file via -F argument:
$ ssh -F my.conf
Is there any way that I can pass content of my.conf to ssh without creating config file?
You can write the config file content to a temporary file and delete it after using it for your ssh connection:
mktemp | xargs -t -I {} sh -c 'echo "your ssh config content" > {}; ssh -F {} HOST; rm {}'

Properly Escape $ in a nested remote command

I would like to execute a command on a remote host from another remote host.
HOST1=host1.domain.tld
HOST2=host2.domain.tld
HOST1 is used to connect to HOST2 and the command executes on HOST2. The remote command depends a variable that is calculated on HOST2.
ssh -A $HOST1 -C "x=wrong; ssh -A $HOST2 -C "x=right; echo \$x""
Strangely, the above returns $x while the next command returns wrong instead of an empty line.
ssh -A $HOST1 -C "x=wrong; ssh -A $HOST2 -C "echo \$x""
Question 1: Why is the first command giving me $x?
Question 2: Keeping the double quotes, how do I have it print right?
Section 1: Literal Answers
...to the question precisely as-asked.
Why is the first command giving me $x?
Keep in mind that this command is executed multiple times, and is thus transformed by multiple shells. That transformation looks something like the following (assuming HOST1 of 1.1.1.1 and HOST2 of 2.2.2.2):
ssh -A 1.1.1.1 -C "x=wrong; ssh -A 2.2.2.2. -C "x=right; echo \$x""
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^
...note the arrows? Those are showing where your quoted regions begin and end: Your quote just before x=right is ending your quote that started before x=wrong!
Thus, this tokenizes to two separate commands, written out with one shell word per line below:
# command one: ssh
ssh \
-A \
1.1.1.1 \
-C \
"x=wrong; ssh -A 2.2.2.2. -C "x=right;
# command two: echo
echo \
\$x""
Keeping the double quotes, how do I have it print right?
Backslash-escape the nested quotes so they don't close the quotes you intend to be outer.
ssh -A $HOST1 -C "x=wrong; ssh -A $HOST2 -C \"x=right; echo \$x\""
Section 2: Best-Practice Alternatives
SSH - ProxyCommand
In practice, don't do this kind of explicit nested SSH invocation at all -- just use the ProxyCommand ssh config option:
ssh \
-o "ProxyCommand ssh $HOST1 netcat -w 120 %h %p' \
"$HOST2" 'x=right; echo "$x"'
Bash - nestable eval-safe quote generation
In general, trying to escape things by hand is much more error-prone than telling the shell to do it for you.
host2_cmd='x=right; echo "$x"'
printf -v host1_cmd '%q ' ssh -A "$HOST2" -C "$host2_cmd"
ssh "$HOST1" bash -s <<<"$host1_cmd"
To demonstrate, we could even do this with a third host in the way:
host3_cmd='x=right; echo "$x"'
printf -v host2_cmd '%q ' ssh -A "$HOST3" -C "$host3_cmd"
printf -v host1_cmd '%q ' ssh -A "$HOST2" -C "$host2_cmd"
ssh "$HOST1" bash -s <<<"$host1_cmd"
This works because in ksh and bash, printf %q quotes a string in such a way that it'll evaluate to its current contents when parsed by that same shell.

echo quotes in bash script

I'm creating an automatic network configuration script and in it i have
#!/bin/bash
sudo rm /etc/default/ifplugd
sudo echo "INTERFACES=""
HOTPLUG_INTERFACES="wlan0 eth0"
ARGS="-q -f -u0 -d10 -w -I"
SUSPEND_ACTION="stop"" > /etc/default/ifplugd
however on viewing /etc/default/ifplugd some of the quotes are missing
INTERFACES=
HOTPLUG_INTERFACES=wlan0 eth0
ARGS=-q -f -u0 -d10 -w -I
SUSPEND_ACTION=stop
How do I configure the script so it includes the quotes between the first and last echo ones?
How about:
sudo sh -c 'cat <<END >/etc/default/ifplugd
INTERFACES=""
HOTPLUG_INTERFACES="wlan0 eth0"
ARGS="-q -f -u0 -d10 -w -I"
SUSPEND_ACTION="stop"
END
'
You don't need to explicitly rm, the > redirection will truncate the file before writing the new content.
You need to escape the " marks with a \ prefix, like this:
#!/bin/bash
sudo rm /etc/default/ifplugd
sudo echo "INTERFACES=\"\"
HOTPLUG_INTERFACES=\"wlan0 eth0\"
ARGS=\"-q -f -u0 -d10 -w -I\"
SUSPEND_ACTION=\"stop\"" > /etc/default/ifplugd
A heredoc provides an elegant solution:
sudo tee << EOF /etc/default/ifplugd
INTERFACES=""
HOTPLUG_INTERFACES="wlan0 eth0"
ARGS="-q -f -u0 -d10 -w -I"
SUSPEND_ACTION="stop"
EOF
This way, you don't have to manually quote each and every "" around, and you are not removing the ifplugd file, so you won't need to reset permissions after creating it.

Resources