echo quotes in bash script - bash

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.

Related

Multiline heredoc with sudo in Dockerfile

We use our local repo in sources.list, and for 20.04 it required to add in apt.conf.d
Acquire::https::local_repo.local_host.com::Verify-Peer "false";
With Bash it works, as using,
sudo tee -a /etc/apt/apt.conf.d/80ssl-exceptions > /dev/null <<'EOF'
Acquire::https::local_repo.local_host.com::Verify-Peer "false";
EOF
But I don't find a solution to do it for Dockerfile.
I've tried it with different escape character/new line and so on, but always unsuccessful.
For example,
sudo tee -a /etc/apt/apt.conf.d/80ssl-exceptions > /dev/null <<'EOF' \
Acquire::https::local_repo.local_host.com::Verify-Peer "false"; \
EOF
Results - /bin/sh: 1: EOF: not found
To note that cat or echo is not an option, also adding those 3 line in a script is also not preferable.
If you only have one line to append then I wouldn't use a heredoc. It's simpler to use echo:
RUN echo 'Acquire::https::local_repo.local_host.com::Verify-Peer "false";' | \
sudo tee -a /etc/apt/apt.conf.d/80ssl-exceptions > /dev/null
Or cat:
RUN cat <<< 'Acquire::https::local_repo.local_host.com::Verify-Peer "false";' | \
sudo tee -a /etc/apt/apt.conf.d/80ssl-exceptions > /dev/null
Or send the string directly to sudo tee:
RUN sudo tee -a /etc/apt/apt.conf.d/80ssl-exceptions > /dev/null \
<<< 'Acquire::https::local_repo.local_host.com::Verify-Peer "false";'
Note that the latter two options may require you to also set SHELL /bin/bash since <<< is a bash-ism not available in plain sh.

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

Some Output Lost in Command Passed to SSH

I'm trying to use an ssh command to ssh to a server and run theuseradd command I passed to it. It seems like its running ok for the most part (no errors produced) but the hashed password in the /etc/shadow file is missing the salt (I believe that's the portion that's missing.).
I'm not sure if the quoting that is incorrect or not. But running this command manually on the server works fine, so I'm assuming its the expansion that's messed up.?
The command below is running inside a Bash script...
Command:
ssh user#$host "useradd -d /usr/local/nagios -p $(perl -e 'print crypt("mypassword", "\$6\$salt");') -g nagios nagios && chown -R nagios:nagios /usr/local/nagios"
*When I escape the double quotes inside the perl one-liner, I get the error:
Can't find string terminator '"' anywhere before EOF at -e line 1.
Usage: useradd [options] LOGIN
Any idea what I'm doing wrong here?
Instead of enclosing the entire command in double-quotes and making sure to correctly escape everything in it, it will be more robust to use single-quotes, and handle embedded single-quotes as necessary.
In fact there are no embedded single-quotes to handle,
only the embedded literal $ in the $6$salt.
ssh "user#$host" 'useradd -d /usr/local/nagios -p $(perl -e "print crypt(q{mypassword}, q{\$6\$salt});") -g nagios nagios && chown -R nagios:nagios /usr/local/nagios'
echo "useradd -d /usr/local/nagios -p $(perl -e 'print crypt("mypassword", "\$6\$salt");') -g nagios nagios && chown -R nagios:nagios /usr/local/nagios" > /tmp/tempcommand && scp /tmp/tempcommand root#server1:/tmp && ssh server1 "sh -x /tmp/tempcommand && finger nagios && rm /tmp/tempcommand"
In such cases I always prefer to have a local file on the local/remote server from which I execute the command set. Saves a lot of "quotes debugging time". What I am doing above is first to save the long one-liner to a file locally, "as is" and "as works" locally, copy it over with scp to the remote server and execute it there with the shell.
More secure way (no need to copy over the file). Again - save it locally and pass it to the remote bash with -s option :
echo "useradd -d /usr/local/nagios -p $(perl -e 'print crypt("mypassword", "\$6\$salt");') -g nagios nagios && chown -R nagios:nagios /usr/local/nagios" > /tmp/tempcommand && echo finger nagios >> /tmp/tempcommand && ssh server1 'bash -s' < /tmp/tempcommand

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

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

Resources