I am using a VPN server on a vps. The VPN service I use can of course go down for a few minutes or maybe even hours by accident or whatever. If it happens, I would like to quickly reconnect to another vpn-server with the command "vpnapp reconnect".
Does anyone know how to do a bash script I will run every minute via cronjob that:
Pings google.com
2A) If it can be reached, do nothing
2B) If it cannot be reached - which would mean the vpn server is down/not working - enter terminal command "vpnapp reconnect" which will make the vpn application reconnect to next available server they offer.
Would be so thankful if anyone could help me. I have ZERO programming knowledge. To me this is pure science.
Thanks in advance.
Oski
Can it be this simple?
if ping -c 4 google.com ; then exit ; else vpnapp reconnect ; fi
So if 4 packages are received, meaning google.com can be reached it will just exit the bash script.
if not, then it will just enter
vpnapp reconnect
as a command in the terminal... reconnecting the vpn.
or does it need to be "vpnapp reconnect" embedded in "?
Lol i am so weak at this. I really dont trust my own suggestion anyway so would love to hear a real programmer speak. Thanks!!
You don't need a bash script, you can just add this cron job (with crontab -e):
* * * * * ping -c2 google.com || vpnapp reconnect
* * * * * Run the command every minute.
ping -c2 google.com Send 2 pings to google.com.
|| vpnapp reconnect mean that if ping failled it will run vpnapp reconnect
I am creating a script to kickstart several servers. I am nearly finished, however I want the bash script to wait until the server kickstart is done.
When the kickstart is done and the server is rebooted a file will be created on the remote kickstarted server which is located under "/root/" and is called "kickstart-DONE"
Is it possible to make the bash script wait until it sees this file and then post something like "Done!"...?
I tried searching the forums and internet, but probably I am searching incorrectly, as I was unable to find something relevant to this issue. Heck, I don't even know if this is possible at all.
So in short; I run my script which kickstarts a server. After the kickstart is done it will create a file on the remote (- kickstarted) server called: kickstart-DONE. This would be an indication for the script that the kickstart is fully done and the server can be used. How do I make the script aware of this?
I hope someone understands what I mean and trying to achieve....
Thanks in advance.
//EDIT
SOLVED! Thanks to Cole Tierney!
Cole Tierney gave some good answers, however though it works it does not wait until the server is kickstarted. I ran the script to kickstart a server and in the end it was running the provided command:
ssh root#$HWNODEIP "while ! test -e /root/kickstart-DONE; do sleep 3; done; echo KICKSTART IS DONE...\!"
However since the kickstart can take some time (depending on server speed and such; ranging from 15 minutes to 1 hour). The command timed out:
ssh: connect to host 100.125.150.175 port 22: Connection timed out
Is there a way that the script does not time out at all and keeps it alive until the server gets back or until it takes more than 1 hour or so?
Maybe there is also a way to make it show that the script is still active? Like "Waiting... 5 minutes passed." "Waiting... 10 minutes passed." etc.
So it gives the current user some information that it not died?
You could call sleep until the file exists:
while ! test -e /root/kickstart-DONE; do sleep 3; done; echo kickstart done
Or sleep until the server is accepting ssh connections. Run the following netcat command locally to check when port 22 is open on the server (remove echo closed; if you don't want the extra feedback):
while ! nc -zw2 $HWNODEIP 22; do echo closed; sleep 3; done
On a side note, it's useful to setup a host entry in ~/.ssh/config. You can add all sorts of ssh options here without making your ssh command unwieldy. Options that are common to all host entries can be added outside of the host entries. See man ssh_config for other options. Here's an example (server1 can be anything, replace <server ip> with the server's ip address):
Host server1
Hostname <server ip>
User root
Then to use it:
ssh server1 'some command'
Note that many systems will not allow ssh connections from root for security reasons. You may want to consider adding another user for kickstart stuff. Add this user to sudoers if root access is needed.
I'm having an issue but I can't see something related with this.
I'm having an issue, something is happening while I'm performing an FTP connection with a server is transferring a file, but for some reason sometimes is stuck but I would like to prevent have the connection opened, there is a way to see if the FTP connection is not transferring, close the connection?
I really don't have any code due I'm not sure if this is possible,
Any idea what can I do at this point?
If it is closing the connection while you are transferring files, then it's either your FTP/SFTP client, server, or network. First, Switch to a different FTP/SFTP client. Some have more tools for analysis than others. I have had to do this before. If that doesn't work, check the internet connection or contact your system/network administrator.
there is a way to see if the FTP connection is not transferring, close
the connection?
If you are downloading a file, you can indirectly see the FTP transferring by watching the file's size:
name=$1
size=0
while sleep 10
set -- `ls -s $name`
[ "$1" -gt $size ]
do size=$1
done
exit 1
The above script (let's call it growing) runs while the file (passed as a parameter) grows.
In your script you could write something like
growing file || pkill ftp &
before you start the FTP. If the file stops growing for ten seconds, ftp would be killed and the connection thereby closed. If ftp terminates normally, you could kill $! or just let growing end.
I'm downloading huge sums of data at night and my PC in running through a UPS. Is there any way I can detect a power failure and command my PC to shut down automatically? Because I work at night, and there's no one to switch off the PC, it would be really helpful if anyone could help. Is it possible?
Thanks.
IMPORTANT: The scripts presented below will cause the system to shutdown whenever the network is down, so use them at your own risk!
A not so elegant way of doing what you want, if you have a network host (e.g. your router) that responds to ICMP echo requests and is not powered by the UPS (or at least the networking equipment is not powered by the UPS), would be to ping that host every few seconds and if it's down then shutdown the PC:
#!/bin/bash
while :
do
ping -c 1 -w 5 192.168.0.1 &> /dev/null
if [ $? -gt 0 ]; then
shutdown -hP now
break
fi
sleep 10s
done
You will have to change 192.168.0.1 to the IP address of the network host you want to ping.
You will also have to make the script executable with chmod +x <script_name> and place a call to it in /etc/rc.local (do not forget to append a & to make it run in the background) which will run the script as root on boot.
For completeness' sake, if the PC was running Windows XP one could use the following batch file:
:loop
ping -n 1 -w 5000 192.168.0.1
if not %ERRORLEVEL% == 0 (
shutdown -s
goto end
)
sleep 10
goto loop
:end
Note that the Windows batch file requires the sleep command which can be installed as part of the Windows Server 2003 Resource Kit Tools package (available as a free download from Microsoft's site)
If it's an APC and it has a data port you can use PowerChute. It's a java-based GUI (which could be a problem if this is your server) that does exactly what you are requesting.
I'm trying to write a shell script that automates certain startup tasks based on my location (home/campusA/campusB). I go to University and take classes in two different campuses (hence campusA/campusB). My location is determined by which wireless network I'm connected to. For the purposes of this script, we can assume that I will be connected to one of these networks when the script is called and my script knows which one I'm connected to based on a call to iwconfig.
This is what I want it to do:
cat file1 > file2 # always do this, regardless of where I am
if Im at home:
start tweetdeck, thunderbird, skype
else if Im at campusA:
activate the login script # I need to login on a webform before I get internet access.
# I have written a script to automate this.
# Wait for this script to finish before doing anything else
myProg2 & # I want myProg2 running in the background until I shutdown my computer.
else if Im at campusB:
ssh username#domain # this is the problematic line
myProg2 & # I want myProg2 running in the background until I shutdown my computer.
start tweetdeck, thunderbird
close the terminal with the "exit" command
The problem is that campusB's wireless network is behind a firewall, which grants me internet access ONLY after I successfully ssh by username#domain. After a successful ssh, I need to keep the terminal window active in order to hold keep the internet access. If I close the terminal window, I lose internet access (this is bad).
When I try doing just ssh username#domain, the script stops because I don't exit the ssh command. I can't ^C out of it, which means that the rest of the script is never executed. I also have the same problem if I just close the terminal window in an attempt to kill the ssh session.
Some googling brought me to subshell, which I'm either using wrong or can't use to solve my problem. So how should I go about solving this problem? I'd appreciate any help - I've been at this for a while now and am unable to find anything helpful. If it makes a difference, I'd rather not store my ssh password in the script
Further, ampersanding the ssh call (ssh username#domain &) doesn't seem to do any good (can anyone explain why?)
Thank you in advance
EDIT
I must clarify, that the ssh connection has to be active in order for me to have internet access. Thus, when I close the terminal window, I need the ssh connection to still be active.
I had a script that looped on 6 servers, calling via ssh in the background. In 1 part of the script, there was a mis-behaving vendor application; the application didn't 'let go' of the connection properly. (other parts of the script using ssh in background worked fine).
I found that using ssh -t -t cured the problem. Maybe this can help you too.
(a teammate found this on the web, and we had spent so much time, I never went back to read the article that suggested this. The man page on our system gave no hint that such a thing was possible)
Hope this helps.
You may want to try to double background myProg2 to detach it from the tty:
# cf. "Wizard Boot Camp, Part Six: Daemons & Subshells",
# http://www.linux-mag.com/id/5981
(myProg2 &) &
Another option may be to use the daemon tool from the libslack package:
http://ingvar.blog.linpro.no/2009/05/18/todays-sysadmin-tip-using-libslack-daemon-to-daemonize-a-script/
Having a ssh with pseudy tty on background shell
In addition to #shellter's answer, I would like make some precision:
where #shelter said:
The man page on our system gave no hint that such a thing was possible
On my system (Debian 7 GNU/Linux), if I hit:
man -Pcol\ -b ssh| grep -A3 '^ *-t '
I could read:
-t Force pseudo-tty allocation. This can be used to execute arbi‐
trary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
Yes: Multiple -t options force tty allocation, even if ssh has no local tty.
This mean: If you remotely run a tool that require access to pseudo terminal ( pty like /dev/pts/0), you could run them by using -t switch.
But this would work only if ssh is run from a shell console (aka having his own pty). If you plan to run them is shell session without console, like background scripts, you may use Multiple -t to enforce pseudo tty allocation from ssh.
Multiple ssh shell on one ssh connection
In addition to answers from #tommy and #geekosaur, I would make some precision:
#tommy point to a very intersting feature of ssh. Not sure this have a lot to do with answer, but speaking around long time connection, this feature has to be clearly understood.
Once a connection is established, ssh could (and know how to) use them to drive a lot of thing in this one connection:
-L let you drive remote TCP connections to local machines/network. (full syntax is: -L localip:localport:distip:distport) where localip could be specified to permit other hosts from same local domain to access same tcp bind, and distip could by any host from distant network ( not only localhost ) sample: -L192.168.1.31:8443:google.com:443 permit any host from local domain to reach google through your host: http://192.168.1.31:8443
-R Same remarks in reverse way!
-M Tell ssh to open a local unix socket for bindind next ssh consoles. Simply open two terminal window. First in both window, hit: ssh somewhere than hit netstat -tan | grep :22 or netstat -tan | grep 192.168.1.31:22 (assuming 192.168.1.31 is your onw host's ip)
Than compare close all your ssh session and in first terminal, hit: ssh -M somewhere and in second, simply ssh somewhere. you may see in second terminal:
$ ssh somewhere
+ ssh somewhere
Last login: Mon Feb 3 08:58:01 2014 from elsewhere
If now you hit netstat -tan | grep 192.168.1.31:22 (on any of two oppened ssh session;) you must see that there is only one tcp connection.
This kind of features could be used in combination with -L and maybe some sleep 86399...
To work around a tcp killer router that close every inactive TCP connection from more than 120 seconds, I run:
ssh -M somewhere 'while :;do uptime;sleep 60;done'
This ensure connection stay up even if I dont hit a key for more than two minutes.
Here's a few thoughts that might help.
Sub-shells
Sub-shells fork new processes, but don't return control to the calling shell. If you want to fork a sub-shell to do the work for you, then you'll need to append a & to the line.
(ssh username#domain) &
But this doesn't look like a compelling reason to use a sub-shell. If you had a number commands you wanted to execute in order from each other, yet in parallel from the calling shell, then maybe it would be worth it. For example...
(dothis.sh; thenthis.sh; andthislastthingtoo.sh) &
Forking
I'm not sure why & isn't working for you, but it may be worth looking into nohup as well. This makes the command "immune" to hang up signals.
nohup ssh username#domain (try with and without the & at the end)
Passwords
Not storing passwords in the script is essential for any ssh automation. You can accomplish that using public key cryptography which is an inherent feature of ssh. I wont go into the details here because there are a number of great resources all across the interwebs on setting this up. I strongly suggest investigating this further.
HOWTO: set up ssh keys - Paul Keck, 2001
SSH Keys - archlinux.org
SSH with authentication key instead of password - Debian Administration
Secure Shell - Wikipedia, the free encyclopedia
If you do go this route, I also suggest running ssh in "batch mode" which will disable password querying and will automatically disconnect from the server if it becomes unresponsive after 5 minutes.
ssh -o 'BatchMode=yes' username#domain
Persistence
Then if you want to persist the connection, run some silly loop in bash! :)
ssh -o 'BatchMode=yes' username#domain "while (( 1 == 1 )); do sleep 60; done"
The problem with & is that ssh loses access to its standard input (the terminal), so when it goes to read something to send to the other side it either gets an error and exits, or is killed by the system with SIGTTIN which will implicitly suspend it. The -n and -f options are used to deal with this: -n tells it not to use standard input, -f tells it to set up any necessary tunnels etc., then close the terminal stream.
So the best way to do this is probably to do
ssh -L 9999:localhost:9999 -f host & # for some random unused port
and then manually kill the ssh before logout. Alternately,
ssh -L 9999:localhost:9999 -n host 'while :; do sleep 86400; done' </dev/null &
(The redirection is to make sure the SIGTTIN doesn't happen anyway.)
While you're at it, you may want to save the process ID and shut it down from your .logout/.bash_logout:
ssh -L 9999:localhost:9999 -n host 'while :; do sleep 86400; done' < /dev/null & echo $! >~.ssh_pid; chmod 0600 ~/.ssh_pid
and in .bash_logout:
if test -f ~/.ssh_pid; then
set -- $(sed -n 's/^\([0-9][0-9]*\)$/\1/p' ~/.ssh_pid)
if [ $# = 1 ]; then
kill $1 >/dev/null 2>&1
fi
rm ~/.ssh_pid
fi
The extra code there attempts to avoid someone sabotaging your ~/.ssh_pid, because I'm a professional paranoid.
(Code untested and may have typoes)
It's been a while since I've used ssh, and I can't test it right now, but have you tried the -f switch?
ssh -f username#domain
The man page says it backgrounds ssh. Not sure why & wouldn't work, but I guess it's interpreting it as a command to be run on the remote machine.
Maybe screen + ssh would fit the bill as well?
Something like:
screen -d -m -S sessionName cmd
screen -d -m -S sessionName cmd &
# reconnect with
screen -r sessionName