Small script involving grep to pass on for the next command - bash

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.

Related

how does bash do `ssh` autocompletion?

I've got the "bash-completion" package installed.
ssh completion on the command line (in bash) is working: ssh TAB-TAB will complete past used hosts and ssh -TAB-TAB will complete available ssh options.
However when I search for currently defined completions:
$ complete | grep ssh
complete -F _known_hosts ssh-installkeys
complete -F _service /etc/init.d/ssh
... I find that there's no completion registered for ssh ?!
complete -p ssh
bash: complete: ssh: no completion specification
When I check the ssh completions script under /usr/share/bash-completion/completions/ssh then I see that indeed it does register ssh completions:
$ grep complete /usr/share/bash-completion/completions/ssh | grep ssh | grep -v '^#'
shopt -u hostcomplete && complete -F _ssh ssh slogin autossh sidedoor
So why doesn't the ssh completion show up in complete | grep ssh? How does bash complete the ssh options?
If there is no completion defined for a command (or a function or whatever) then the "default" completer kicks in.
That default completer can be seen here:
$ complete -p -D
complete -F _completion_loader -D
When the bash-completion package is installed, then that will source /usr/share/bash-completion/bash_completion via /etc/bash.bashrc and that will assign the _completion_loader function.
_completion_loader will dynamically load specific completers upon completion request for commands the shell's completer doesn't know about yet (see here).
In the case of ssh, the terminals where I was doing the poking around had not yet loaded the ssh completer and so I was not seeing it with complete | grep ssh or complete -p ssh. It's only at the moment when you press TAB-TAB for the first time that the completer for ssh gets loaded.

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.

Update root crontab remotely for many systems by script

I am trying to update the crontab file of 1000+ systems using a for loop from jump host.
The below doesn't work.
echo -e 'pass365\!\n' | sudo -S echo 'hello' >> /var/spool/cron/root
-bash: /var/spool/cron/root: Permission denied
I do have (ALL) ALL in the sudoers file.
This is another solution;
echo 'pass365\!' | sudo -S bash -c 'echo "hello">> /var/spool/cron/root'
The below worked for me.
echo 'pass365\!' | sudo -S echo 'hello' | sudo -S tee -a /var/spool/cron/root > /dev/null
Problem 1: You are trying to send the password via echo to sudo.
Problem 2: You can't use shell redirection in a sudo command like that.
Between the two of these, consider setting up ssh public key authorization and doing
ssh root#host "echo 'hello' \>\> /var/spool/cron/root"
You may eventually get sudo working but it will be so much more pain than this.

sudo'd mysqldump over ssh syntax?

I'd like a single command that:
ssh's into my server as user foo, using the public keys I have set up
executes a mysqldump of some database with the /etc/mysql/debian.cnf defaults-file
to stdout, so I can pipe it locally
while doing a sudo on the server remotely, because user foo is not allowed to read /etc/mysql/debian.cnf. foo is allowed to sudo bash but not sudo mysqldump.
This is the best I have come up:
echo 'mysqldump --defaults-file=/etc/mysql/debian.cnf dbname' | ssh -t -i keys/id_rsa -l foo example.com sudo bash -s
This ugly beast works, but produces: Pseudo-terminal will not be allocated because stdin is not a terminal., and I really don't like the echo. There must be a better way?
ssh -i keys/id_rsa foo#example.com sudo bash -c "'mysqldump --defaults-file=/etc/mysql/debian.cnf dbname'"
This will only work if sudo doesn't need to ask for a password. If it does, you need the -t option to ssh.
Note the double and single quotes. The outer quotes will get taken away by your local shell, and the whole 'mysqldump --defaults-file=/etc/mysql/debian.cnf dbname' string will be passed to ssh as a single argument. Ssh will pass that to the remote sudo, so your remote will see the single quotes. The remote bash needs the single quotes to interpret the part after -c as a single argument.

Sudo not prompting for password Mac bash script

I am trying to write a script that appends a line to the /etc/hosts, which means I need sudoer privileges. However, if I run the script from the desktop it does not prompt for a password. I simply get permission denied.
Example script:
#!/bin/bash
sudo echo '131.253.13.32 www.google.com' >> /etc/hosts
dscacheutil -flushcache
A terminal pops up and says permission denied, but never actually prompts for the sudo password. Is there a way to fix this?
sudo doesn't apply to the redirection operator. You can use either echo | sudo tee -a or sudo bash -c 'echo >>':
echo 131.253.13.32 www.google.com | sudo tee -a /etc/hosts
sudo bash -c 'echo 131.253.13.32 www.google.com >> /etc/hosts'
What you are doing here is effectively:
Switch to root, and run echo
Switch back to yourself and try to append the output of sudo onto
/etc/hosts
That doesn't work because you need to be root when you're appending to /etc/hosts, not when you're running echo.
The simplest way to do this is
sudo bash -c "sudo echo '131.253.13.32 www.google.com' >> /etc/hosts"
which will run bash itself as root. However, that's not particularly safe, since you're now invoking a shell as root, which could potentially do lots of nasty stuff (in particular, it will execute the contents of the file whose name is in the environment variable BASH_ENV, if there is one. So you might prefer to do this a bit more cautiously:
sudo env -i bash -c "sudo echo '131.253.13.32 www.google.com' >> /etc/hosts"

Resources