Bash scripting || sed command - bash

I am trying to add # in front of a line if string gets a match.
String will be read by user.
Direct sed command well for me but when is user read command then it throws error:
server cust01-stg01-ins01-wfm13-bck-610358970-22.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-25.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-21.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-23.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-24.int.stg.mykronos.com:80 resolve max_fails=0;
Now suppose user want to comment line with matching character "cust01-stg01-ins01-wfm13-bck-610358970-22" then below output is expected
#server cust01-stg01-ins01-wfm13-bck-610358970-22.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-25.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-21.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-23.int.stg.mykronos.com:80 resolve max_fails=0;
server cust01-stg01-ins01-wfm13-bck-610358970-24.int.stg.mykronos.com:80 resolve max_fails=0;
sudo sed -i "/cust01-stg01-ins01-wfm13-bck-610358970-23/s/^/#/" wfm_backend_nginx.state
this works well for me but when I am trying below command then it is throwing error.
[root#cust01-stg01-ins01-wfm13-bck-ilb1-610358970 tmp]# cat ilb_commnet.sh
#!/bin/bash -xe
sudo read -p "enter host_name :" Host
sudo sed -i -e "/${Host}/s/^/#/" /tmp/wfm_backend_nginx.state
Output is :
sed: -e expression #1, char 0: no previous regular expression

sudo read -p "enter host_name :" Host
sudo runs a separate process, that will read the input and save it into Host. Then the process will exit, destroying the whole environment with the read value.
Remove sudo - read the value in current process.

Using sudo is completely crazy here. You are running read in a privileged subshell, which then exits and takes the variable with it before you can use it for anything.
... Actually sudo read is simply a syntax error because sudo can't run a shell built-in. It tries to look for /usr/bin/read, /bin/read etc but doesn't find anything.
bash$ sudo read -p hello
sudo: read: command not found
Even without the sudo, your code should probably examine the variable before attempting to pass it to a privileged command. Maybe something like
#!/bin/bash -xe
while true; do
read -p "Enter host name: " Host
case $Host in
*[!A-Za-z0-9]*) echo "$0: Invalid characters in host name" >&2;;
*) break
esac
done
sudo sed -i -e "/${Host}/s/^/#/" /tmp/wfm_backend_nginx.state

Related

Bash: get output of sudo command on remote using SSH

I'm getting incredibly frustrated here. I simply want to run a sudo command on a remote SSH connection and perform operations on the results I get locally in my script. I've looked around for close to an hour now and not seen anything related to that issue.
When I do:
#!/usr/bin/env bash
OUT=$(ssh username#host "command" 2>&1 )
echo $OUT
Then, I get the expected output in OUT.
Now, when I try to do a sudo command:
#!/usr/bin/env bash
OUT=$(ssh username#host "sudo command" 2>&1 )
echo $OUT
I get "sudo: no tty present and no askpass program specified". Fair enough, I'll use ssh -t.
#!/usr/bin/env bash
OUT=$(ssh -t username#host "sudo command" 2>&1 )
echo $OUT
Then, nothing happens. It hangs, never asking for the sudo password in my terminal. Note that this happens whether I send a sudo command or not, the ssh -t hangs, period.
Alright, let's forget the variable for now and just issue the ssh -t command.
#!/usr/bin/env bash
ssh -t username#host "sudo command" 2>&1
Then, well, it works no problem.
So the issue is that ssh -t inside a variable just doesn't do anything, but I can't figure out why or how to make it work for the life of me. Anyone with a suggestion?
If your script is rather concise, you could consider this:
#!/usr/bin/env bash
ssh -t username#host "sudo command" 2>&1 \
| ( \
read output
# do something with $output, e.g.
echo "$output"
)
For more information, consider this: https://stackoverflow.com/a/15170225/10470287

Syntax error when calling variable in bash

Here is my code:
#!bin/bash
id=$(sshpass -p password ssh -tt username#ipaddress -p PORT "grep --include=\*.cr -rlw '/usr/local/bin/' -e '$1' | cut -c16-")
echo $id
sshpass -p password rsync -avHPe 'ssh -p PORT' username#ipaddress:/usr/local/bin/"$id" /usr/local/bin/
id echos correctly, but I get an rsync error when trying to call the variable.
If I manually populate and run rsync, the command works, so I'm not sure what is going on.
Rsync gives me the following output on error.
rsync: link_stat "/usr/local/bin/match.cr\#015" failed: No such file or directory (2)
It seems to be grabbing extra characters? Any help is appreciated :)
Looks like your file contains Windows specific "CR LF" characters. You need to convert these to Linux specific "LF" characters in your script. You can use a tool like dos2unix or Notepad++.

Running sudo via ssh on remote server

I am trying to write a deployment script which after copying the new release to the server should perform a few sudo commands on the remote machine.
#!/bin/bash
app=$1
echo "Deploying application $app"
echo "Copy file to server"
scp -pr $app-0.1-SNAPSHOT-jar-with-dependencies.jar nuc:/tmp/
echo "Execute deployment script"
ssh -tt stefan#nuc ARG1=$app 'bash -s' <<'ENDSSH'
# commands to run on remote host
echo Hello world
echo $ARG1
sudo ifconfig
exit
ENDSSH
The file gets copied correctly and the passed argument printed as well. But the prompt for the password shows for two seconds then it says "Sorry, try again" and the second prompt shows the text I enter in plain text (meaning not masked) but also does not work if I enter the password correctly.
stefan#X220:~$ ./deploy.sh photos
Deploying application photos
Copy file to server
photos-0.1-SNAPSHOT-jar-with-dependencies.jar 100% 14MB 75.0MB/s 00:00
Execute deployment script
# commands to run on remote host
echo Hello world
echo $ARG1
sudo ifconfig
exit
stefan#nuc:~$ # commands to run on remote host
stefan#nuc:~$ echo Hello world
Hello world
stefan#nuc:~$ echo $ARG1
photos
stefan#nuc:~$ sudo ifconfig
[sudo] password for stefan:
Sorry, try again.
[sudo] password for stefan: ksdlgfdkgdfg
I tried leaving out the -t flags for ssh as well as using -S for sudo which did not help. Any help is highly appreciated.
What I would do :
ssh stefan#nuc bash -s foobar <<'EOF'
echo "arg1 is $1"
echo "$HOSTNAME"
ifconfig
exit
EOF
Tested, work well.
Notes :
for the trick to work, use ssh key pair instead of using a password, it's even more secure
take care of the place of your bash -s argument. Check how I pass it
no need -tt at all
no need sudo to execute ifconfig and better use ip a
I came up with another solution: Create another file with the script to execute on the remote server. Then copy it using scp and in the calling script do a
ssh -t remoteserver sudo /tmp/deploy_remote.sh parameter1
This works as expected. Of course the separate file is not the most elegant solution, but -t and -tt did not work when inlining the script to execute on the remote machine.

Small script involving grep to pass on for the next command

My network card's name keeps alternating names between enp4s0 and enp3s0 after startup. In addition, it also starts DOWN. Everytime I login I have to do this, manually:
ip link # it outputs the names
sudo ip link set enpXs0 up
sudo dhcpcd
So I tried to make a small script to be run with .xinitrc. This is what I came up with:
#!/bin/bash
CARD=ip link | grep -o enp[4\|5]s0
echo ${CARD} # check
sudo ip link set ${CARD} up
sudo dhcpcd
but it doesn't work: link: missing operand. I thought I have to use quotes when assining CARD, it's not so. Neither is using full path names (/usr/bin/ip). How to set up the CARD variable?
#!/bin/bash
CARD=`ip link | grep -o enp[4\|5]s0` #here in card need save result
echo ${CARD} # check
sudo ip link set ${CARD} up
sudo dhcpcd
Command substitution.
Command substitution:
#!/bin/bash
CARD=$(ip link | grep -o enp[4\|5]s0) #here in card need save result
echo ${CARD} # check
sudo ip link set ${CARD} up
sudo dhcpcd
Backtick are not recommended while using command substitution.

How to copy echo 'x' to file during an ssh connection

I have a script which starts an ssh-connection.
so the variable $ssh start the ssh connection.
so $SSH hostname gives the hostname of the host where I ssh to.
Now I try to echo something and copy the output of the echo to a file.
SSH="ssh -tt -i key.pem user#ec2-instance"
When I perform a manual ssh to the host and perform:
sudo sh -c "echo 'DEVS=/dev/xvdbb' >> /etc/sysconfig/docker-storage-setup"
it works.
But when I perform
${SSH} sudo sh -c "echo 'DEVS=/dev/xvdb' > /etc/sysconfig/docker-storage-setup"
it does not seem to work.
EDIT:
Also using tee is working fine after performing an ssh manually but does not seem to work after the ssh in the script.sh
The echo command after an ssh of the script is happening on my real host (from where I'm running the script, not the host where I'm performing an ssh to). So the file on my real host is being changed and not the file on my host where I've performed an ssh to.
The command passed to ssh will be executed by the remote shell, so you need to add one level of quoting:
${SSH} "sudo sh -c \"echo 'DEVS=/dev/xvdb' > /etc/sysconfig/docker-storage-setup\""
The only thing you really need on the server is the writing though, so if you don't have password prompts and such you can get rid of some of this nesting:
echo 'DEVS=/dev/xvdb' | $SSH 'sudo tee /etc/sysconfig/docker-storage-setup'

Resources