How to connect to wifi in bash? - bash

I'd like to make a simple bash script to connect to known wifi networks.
Thus far I have...
#!/bin/bash
NETWORK_ID=${1:myintranet}
WIRELESS_KEY=${2:""}
WIRELESS_DEVICE=${3:wlan0}
if [ ! -n "$WIRELESS_KEY" ]; then
read -s -p "Enter Password: " WIRELESS_KEY
fi
#ifconfig wlan0
iwconfig wlan0 essid $NETWORK_ID key s:$WIRELESS_KEY
dhclient wlan0
I enter the plain text password for the network when requested and it fails with the error
iwconfig: unknown command "s:myPassword"
But I can't find any reason why it should be expecting a command and not translating the key to hex.

This is working fine for me for WEP wifi. Don't forget to name the script with .sh extension.
#!/bin/bash
NETWORK_ID=${1:myintranet}
WIRELESS_KEY=${2:xxx}
WIRELESS_DEVICE=${3:wlan0}
if [ -z "$WIRELESS_KEY" ]; then
read -s -p "Enter Password: " WIRELESS_KEY
fi
#ifconfig wlan0
iwconfig wlan0 essid $NETWORK_ID key s:$WIRELESS_KEY
dhclient wlan0
For WPA wifi, it may not work. Consider using wpa_supplicant or configure it using wicd (wicd-gtk)

Related

bash script stuck at the end of a for loop

I'm trying to deploy $DM_COUNT docker-machines through a script, and write new network configuration to the nodes. The script works fine until the end of the loop and then gets stuck
The script is called from this script:
#!/bin/bash
set -x
PS4='$LINENO: '
net="10.17.65."
The loop starts properly
for i in $(seq 1 $DM_COUNT); do
(
name="$PREFIX$DEPLOYMENTNAME$i"
echo "$name"
if [ -z "$DM_NAMES" ]
then
export DM_NAMES=$name
else
export DM_NAMES=$DM_NAMES:$name
fi
ip="$net$((4 + i))"
mkdir -p ~/.ssh && touch $_/config &&
tee -a $_ << EOF
Host $name
Hostname $ip
User docker
IdentityFile ~/.docker/machine/machines/$name/id_rsa
EOF
docker-machine create $name\
--driver vmwarevsphere \
--vmwarevsphere-cpu-count 4 \
--vmwarevsphere-datastore datastore1 \
--vmwarevsphere-disk-size 60000 \
--vmwarevsphere-memory-size 2048 \
--vmwarevsphere-network 'VM\ Network' \
--vmwarevsphere-vcenter 10.17.6.218 \
--vmwarevsphere-password a \
--vmwarevsphere-username root
docker-machine restart "$name"
docker-machine regenerate-certs -f "$name"
echo 'Done provisioning ' "$name"
docker-machine scp -r /certs/ "$name":/root/certs/
docker-machine ssh "$name" sudo mkdir /var/lib/boot2docker/certs
docker-machine ssh "$name" sudo cp /root/certs/*.crt /var/lib/boot2docker/certs/
echo 'Done copying self-signed certificates'
echo "
# configure eht1 (czlocal1)
sudo ip addr flush dev eth1
sudo ip route del default
sudo ip route add default via 192.168.1.254
# configure eth2 (czlocal2)
sudo ip addr flush dev eth0
sudo ip route add default via 192.168.2.254
# configure eth3 (czlocaldhcp)
sudo ip addr flush dev eth0
# configure eth0 (mgmt)
sudo ip addr flush dev eth0
ip addr add 10.17.65.10$i/24 dev eth0
ip route add 10.17.36.0/24 via 10.17.65.1 dev eth0
ip route add 10.17.33.0/24 via 10.17.65.1 dev eth0
# configure eth2 (czlocal2)
sudo ip addr flush dev eth2
ip addr add 192.168.2.$i/24
# configure eth3 (czlocaldhcp)
sudo ip addr flush dev eth3
" | docker-machine ssh "$name" "sudo tee /var/lib/boot2docker/bootsync.sh"
echo "
sudo ip route del default
sudo ip route add default via 192.168.$1.254
" | docker-machine ssh "$name" "sudo tee ~/switch_default_gateway.sh"
echo "
alias local1='ip route del default && ip route add default via 192.168.1.254'
alias local2='ip route del default && ip route add default via 192.168.2.254'
alias dhcp='ip route del default && ip route add default via 172.0.0.254'
" | docker-machine ssh "$name" "sudo tee -a ~/.bashrc > /dev/null"
echo 'Done writing scripts'
docker-machine ssh "$name" "sudo chmod +x /var/lib/boot2docker/bootsync.sh"
docker-machine ssh "$name" "sudo chmod +x ~/switch_default_gateway.sh"
docker-machine ssh "$name" "source ~/.bashrc"
jq '.Driver.IPAddress = $newVal' --arg newVal '10.17.65.10'$i ~/.docker/machine/machines/"$name"/config.json > tmp.$$.json && mv tmp.$$.json ~/.docker/machine/machines/"$name"/config.json
echo 'Done deploying docker machines'
) &
done
Everything until this point executes fine, then the script is stuck. If I provide any input on the shell it exits.
tee -a ~/.ssh/config << EOF
Host *
StrictHostKeyChecking no
EOF
The last part never gets executed
Are you sure you don't have a 'non breakable space' (https://en.wikipedia.org/wiki/Non-breaking_space) between your << and EOF?
Anyway, your initial script, and the indicated lines at the end of your question is not the same (the one involving tee command), can you update your question to fit the final version of your script?

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.

Feed expect with some variables

I would like to use expect with cryptsetup. It could be whatever program instead of cryptsetup. I feed cryptsetup with a device, a virtual device name and a password.
#!/bin/bash
read -p "Device: `echo $'\n> '`" DEV
read -p "Virtual Device: `echo $'\n> '`" VIRTUAL
read -p "Password: `echo $'\n> '`" PSWD
expect -c exec /sbin/cryptsetup luksOpen /dev/$DEV $VIRTUAL
expect "Enter passphrase for /dev/sdc1:"
send $PSWD
I also tried with 'spawn' but it does not work either.
any idea is more than welcome! thanx folks.
You can overcome the expect dependency by substituting the last three lines of codes with the following :
echo $PSWD | cryptsetup luksOpen /dev/$DEV $VIRTUAL
As I understand you question and comments, you need something like this:
#!/bin/bash
read -p "Device: `echo $'\n> '`" DEV
read -p "Virtual Device: `echo $'\n> '`" VIRTUAL
/sbin/cryptsetup luksOpen /dev/$DEV $VIRTUAL
mount /dev/mapper/$VIRTUAL /mnt/$DEV
cryptsetup will ask you password, you will enter it. After this mount will run. That's all. And you don't need expect and any variable to store password.

ssh keys in known hosts, but keygen -F not working

I found this code elsewhere on stackoverflow:
if [ -z "`ssh-keygen -F ${wPCS_IP}`" ]; then
ssh-keyscan -p ${wPCS_PT} -H ${wPCS_IP} >> ~/.ssh/known_hosts
fi
I have two issues where I'm using the code:
This code is generating an error ($?=1) even though it succeeds.
If I run ssh-keygen -F ${wPCS_IP} again after known_hosts is appended, it does not find the keys in known_hosts, even though they were just added. This is the larger problem.
The local machine is Ubuntu Server 16.04 LTS, the remote machine is Ubuntu Server 14.04 LTS.
The major difference between my code and the code sample I found is my use of the port option -p.
Also, I've noticed that the known_hosts file does not list the machines by name or IP address. Which is different from my Gentoo laptop.
So it turns out that when there's an alternate port for ssh, it is stored in the known_hosts file as part of the IP address in this format:
[${WPCS_IP}]:WPCS_PT
Which means that for the if statement to work, it needs to look like this:
if ! ssh-keygen -F "[${wPCS_IP}]:${WPCS_PT}" -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${wPCS_PT} ${wPCS-IP} >> ~/.ssh/known_hosts; fi
Thanks to alvits for getting me moving in the right direction...
Update: it turns out the Ubuntu 16.04 encrypts the IP address of the remote host (but not the port). I'm still trying to figure out how to adapt to this difference.
Another update: It turns out the the -H option is what's failing. Once you hash the key, it isn't found anymore. This works on Ubuntu 14.04:
if ! ssh-keygen -F ${IP_ADDR} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
# IP_ADDR SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1
# IP_ADDR SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.1
if ! ssh-keygen -F ${IP_ADDR} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
You can see that the first if statement generates the keyscan data and the second does not because the keyscan data is correct, but if you add the -H, the keygen does not detect the hashed key entries...
However, to get a similar command to work on Ubuntu 16.04, the if has to be changed:
if ! ssh-keygen -F [${IP_ADDR}]:${PORT} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
# IP_ADDR:PORT SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
# IP_ADDR:PORT SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
# IP_ADDR:PORT SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8
if ! ssh-keygen -F [${IP_ADDR}]:${PORT} -f ~/.ssh/known_hosts > /dev/null 2>&1; then ssh-keyscan -p ${PORT} ${IP_ADDR} >> ~/.ssh/known_hosts; fi
In this case the known_hosts file must include the port...
-H is right out here as well. The if won't find the key if it was generated with -H.
It's frustrating that the behavior varies from version to version and that the safest hashed version doesn't work.
Yet another edit: It may be the port is specified in known_hosts when the remote server uses a non-standard port in sshd_config. This may be an expected behavior.
I sent an email to the open-ssh list and had several good suggestions. Basically, it is not good to rely on ssh-keygen -F and ssh-keyscan -H as file formats and locations tend to vary from system to system.
The real solution, which I will implement today is to generate certificates for each of the servers so they recognize each other. This works well for me because I have complete control over both servers.
I was given a link that explains how to setup server certificates:
https://blog.habets.se/2011/07/OpenSSH-certificates.html
Here's a link specifically for Ubuntu.
https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with-ubuntu
If this is my last update, assume this worked for me.

Waiting for input from script that is running remotely via ssh

There is a script I'm running that I can not install on the remote machine.
clear && printf '\e[3J'
read -p "Please enter device: " pattern
read -p "Enter date: (YYYY-MM-DD): " date
pfix=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 5 | head -n 1)
mkdir /home/user/logCollectRes/"${pfix}"
ssh xxx.xxx.xxx.xxx 'bash -s' < /usr/local/bin/SearchAdvanced.sh ${pattern} ${date} ${pfix}
In that script, I would like to be able to use read.
ls -g *"${pattern}"*
read -p "Select one of these? [y/n] " "found";
I've tried adding the -n on the read as well as the -t -t option on ssh. As you can see the script presents information that is only seen once the script starts, so I can't use the read on local machine.
EDIT: So lets say server B stores syslogs for 5K computers. The file names are given by using the internal IP of the device and the date at the end.
/var/log/remotes/192.168.1.500201505050736.gz
/var/log/remotes/192.168.1.500201505050936.gz
/var/log/remotes/192.168.1.500201505051136.gz
/var/log/remotes/192.168.1.600201505050836.gz
/var/log/remotes/192.168.1.600201505051036.gz
/var/log/remotes/192.168.1.600201505051236.gz
I'd like to be able to select the IP address from the main script, list all the files matching that IP address, and then select which I want to scp to my local machine.
After speaking with some coworkers I found the answer to be running two scripts: The first pulls the ls -g result and directs the answer to a variable on the local machine. I then print that output with the read option of selecting on of the files. The 2nd script will take that answer and scp the file from the remote machine
In the main script
ssh xxx.xxx.xxx.xxx 'bash -s' < /usr/local/bin/SearchAdvanced.sh ${pattern} ${date} > ${result}
then as a follow up
printf "${result}"
read -p "Select file: "

Resources