I created the following script to install and then uninstall PHPmyadmin on Ubuntu 16.04...

My aim is to use this script each time I want to use PHPmyadmin, and then, after some time like 2 hours, delete it. This install-use-uninstall method is used from security reasons (keeping MySQL inaccessible as possible and accessed only locally for very short periods of time).

bash /dev/fd/15 15<< 'EOF0'    

#!/bin/bash -x

# Install commands:

sudo apt-get install phpmyadmin
sudo phpenmod mcrypt
sudo phpenmod mbstring
cat << EOF1 >> /etc/apache2/apache2.conf

Include /etc/phpmyadmin/apache.conf
sudo service apache2 restart

# Unnstall commands:

sleep 2h    
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf


As noted in the comments by Jeff (and as I edited the code example) I could use the sleep command, but sleep, in its classical form requires that the session will keep open, and the window might close sometimes from whatever reason, so a cannonical answer is needed that shows how to give this 2 hour suspension but in such a way that even if I mistakenly/intentionally close the window, or my PC rebooted from any reason, or there was a power outage --- The suspension and all commands after it will keep running on the VPS, without any interference from my end.

So, how could I execute the uninstall-commands 2 hours after the install-commands, but in a session-independent way?

  • 2
    Would a simple sleep 2h in the middle suffice? – Jeff Schaller Dec 23 '16 at 4:13
  • Might be, I should read on this because I never knew this before... – JohnDoea Dec 23 '16 at 4:16
  • Use multiple screens and run this script on one. This way you'll be able to have it running continuously. – thel3l Dec 23 '16 at 5:10
  • 1
    As Jeff Schaller said add sleep interval. Moreover run this script in background using '&' for running continuously. – Lakshmi Balan Dec 23 '16 at 5:55
  • 1
    Running scripts in background lead to continuous running till we kill that process manually. – Lakshmi Balan Dec 23 '16 at 6:06

You can achieve it with the utility at.

For a single command, do:

at 'now + 2 hours' -f /path/to/uninstall.sh

For multiple commands, serve your script to the shell via cat heredocument:

cat << EOF | at 'now + 2 hours'

Alternatively, you could achieve that with a systemd solution (again, if you have it installed)

systemd-run --on-active=2h -- /bin/bash /path/to/uninstall.sh
  • Hi, deep thanks. Please let me understand something, are you suggesting that I would create a script inside a script? (that is, the code example I gave in the question is already inside a script). – JohnDoea Dec 27 '16 at 20:39
  • @Benia it doesn't have to really be a script inside a script, just as long as that script exists, you can do at 'now + 2 hours' -f uninstall.sh or systemd-run --on-active=2h -- /bin/bash uninstall.sh. If you'd like to entirely avoid creating another script, you can do the cat heredoc piped to at, or systemd-run .... /bin/bash -c 'sudo phpdismod mcrypt mbstring; sudo apt-get purge phpmyadmin; .....' – apricot boy Dec 27 '16 at 23:29
  • I noted a problem with this method here: unix.stackexchange.com/questions/333201/… – JohnDoea Dec 28 '16 at 6:52
  • This didn't work for me in WSL but should work on native Linux system, hence I give the bounty. Thank you Apricot boy. – JohnDoea Dec 31 '16 at 2:51

As I can see you have sudo access and could start services. So you could use atd service and at command to schedule your task:

echo 'touch $HOME/`date -j +%s`.txt' | at + 2 minutes

And for more than one command you have two options:

  1. Combine echo commands:

    (echo "command1"
     echo "command2"
     echo "command3" ) | at + 2 hours
  2. Use temp file for commands list:

     tmp_file=$(mktemp --tmpdir uninstall_commands.XXXX)
     echo "command1" >> ${tmp_file}
     echo "command2" >> ${tmp_file}
     echo "command3" >> ${tmp_file}
     at -f ${tmp_file} + 2 hours
     rm -f -- ${tmp_file}
  • So if I have say 5 uninstall commands I could just add | at + 2 minutes after each one ? Any why to add this to a whole block of commands instead for each one? Thanks! – JohnDoea Dec 27 '16 at 19:51
  • 1
    I've editted my answer and add two options for a list of commands – Fedor Dikarev Dec 27 '16 at 20:10
  • Thank you!, I believe that if you combine echos in parenthesis you should server these stdin data inside a cat heredocument, as these are multiline and not singleline. – JohnDoea Dec 27 '16 at 21:15
  • I noted a problem with this method here: unix.stackexchange.com/questions/333201/… – JohnDoea Dec 28 '16 at 6:52

Assuming two scripts (Do One Thing; Do It Well):


#!/bin/sh -eu
sudo apt-get install phpmyadmin
sudo phpenmod mcrypt mbstring
printf 'Include /etc/phpmyadmin/apache.conf' >> /etc/apache2/apache2.conf
sudo service apache2 restart


#!/bin/sh -eu
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf

The simplest answer I can think of that does exactly what you want is

./install.sh && sleep 2h && ./uninstall.sh >>/var/log/mylog.log 2>&1

where each script additionally includes an ssh command to connect to your server. This approach is resilient to the server power cycling - but not your terminal machine.

As an alternative I would simplify this answer mostly because of the bizarre behaviour of where atd puts its output and instead use

nohup sleep 2h && ./uninstall.sh >>/var/log/mylog.log 2>&1 &

Once executed, you now have approximately 2 hours to do whatever it is you want to do, and after the time is up, the uninstall process will happen. This approach is not resilient to the server power cycling.

This answer avoids dependencies and enables diagnostic/debugging by sensibly capturing and logging relevant output.

  • 1
    This will fail across a reboot – roaima Dec 27 '16 at 23:49
  • I noted a problem with this method here: unix.stackexchange.com/questions/333201/… – JohnDoea Dec 28 '16 at 6:51
  • @roaima How do the details in my answer about reboots fail to capture what your comment is trying to communicate? – Edd Dec 28 '16 at 16:42
  • Your answer doesn't solve the problem the OP is asking, which is to cope with unexpected power outages and other unintended reboots. – roaima Dec 28 '16 at 18:08

First of all, you should structure your code into two scripts, or at least into two separate functions within the same script: the first one for installing, the second one for purging. So you can run either script/function when necessary. Both scripts/functions should also be idempotent, i.e. they should skip installing/purging in case it's already done.

Then, you could simply create a cronjob to call the purging script every 2h, or create a more periodic cronjob that calls the purging script if-and-only-if the installation is at least 2h old. This would survive a reboot of the server, so the package will always be purged.


I am not sure if this solution could fit your requirements, but you can give a try.

If for a moment forget about PC shutdown/reboot , then the following works in bash without trapping terminal (you can try it as one line command for test):

sleep 10 && yad --text="10 seconds passed" && exit &

Above command , although i didn't expect so , works even if i close my terminal window.

PS: If you combine it with nohup will keep the command running even if you log out.

As a workaround you could split your initiall script in two smaller scripts; one script for installation one script for removal, something like this:

sudo apt-get install phpmyadmin
sudo phpenmod mcrypt mbstring
printf 'Include /etc/phpmyadmin/apache.conf' >> /etc/apache2/apache2.conf
sudo service apache2 restart
sleep 7200 && path/to/script_to_remove.sh &
exit #exit the first script to free terminal (or even close the terminal)
#end of script_to_install.sh

#Optionally you can use xterm -e (or similar) to bring up a terminal window automatically to see the output of the commands
sudo phpdismod mcrypt mbstring
sudo apt-get purge phpmyadmin
sudo service apache2 restart
sed -i 's/Include \/etc\/phpmyadmin\/apache.conf/ /g /etc/apache2/apache2.conf
#end of script_to_remove.sh

Coming back to the PC reboot part, i think that this can be solved by writing the start time to a temp log file, and once you reboot, you could monitor that temp file (i.e using inotify tools) to determine time period elapsed (not tested).


In bash, add your script with the sleep statement to your ~/.bash_logout file. In csh, it would be .logout.

I also liked someone's suggestion of using at. You may also want to consider writing a script that acts as a 'police' type function via cron.

I found this on this site which may be useful: How to run a script during Gnome log out


IMHO, this approach of temporarily installing and purging phpmyadmin is an ugly hack. You could simply ssh -L3307:localhost:3306, i.e. you would create a listener on a local port (-L3307) that tunnels and connects to a remote port (localhost:3306). Then, if you would want to talk to the remote MySQL database you would simply use localhost:3307 on the local machine. You wouldn't need to install anything remotely, the tunnel would immediately die on disconnect, and you could use whatever MySQL tool locally (e.g. MySQL Workbench or SQirreL).


There are better ways.

  1. Install phpMyAdmin on a dedicated virtual host with a port you only know (say 56887).

  2. Setup knockd to open that port upon your request, for your IP only.

      sequence      = 2000,3000,4000
      seq_timeout   = 15
      start_command = /usr/sbin/iptables -A INPUT -s %IP% -p tcp --dport 56887 -j ACCEPT
      cmd_timeout   = 7200
      stop_command  = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --dport 56887 -j ACCEPT
  3. Use handy knock to open the port:

    knock myserver.example.com 2000 3000 4000 

That's all! No reinstallation needed. No files moved.

Usual security through obscurity caveats apply. Insecurely configured phpMyAdmin may not be sufficiently protected by any such hack. You must configure it properly no matter what. But if you do, these hacks become unnecessary.


I was able to combine timeout (sleep), external heredoc, internal heredoc(s), nohup, background-level processing, and tty-stdout in the following script.

It's good if you need a fast way to install something and then auto-delete it after some time:

bash /dev/fd/5 5<< 'EOF0'
#!/bin/bash -x

apt-get install SOME_UTILITY1 -y

cat << EOF1 > ~/utility.sh
sleep 1h
apt-get purge SOME_UTILITY1 -y

chmod 755 ~/utility.sh &
nohup ~/utility.sh &


Press return (Enter) when you get the following message, to keep working normally in Bash (the message will appear the moment the script reaches nohup:

nohup: appending output to ‘/USER_LOCATION/nohup.out’

  • This solution is good only if the utility you install doesn't prompt an installation screen above the tty. If it is, then because nohup redirects stdout to ~/nohup.out, it just won't work. See: unix.stackexchange.com/questions/333927/… – JohnDoea Dec 31 '16 at 2:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.