1

As part of a flow that installs Ubuntu 16.04 (from scratch to fully configured, with a lot of extra software installed and changes made post installation), I need a way to run scripts (that are downloaded during installation) after the next reboot (and only the next reboot) and remove the scripts, and end with another reboot.

I already have a service that I use for running scripts after the first boot, but without deleting them (this can be triggered again at a later time if needed), but I now find that I need run scripts that must be deleted afterwards, as they contain sensitive information.

The systemd service I am using for the other scripts look like this:

[Unit]
Description=First run specifics
After=network-online.target
Requires=network-online.target

[Service]
Type=simple
EnvironmentFile=/etc/default/firstrun
ExecStart=/root/bin/firstrun-wrapper "${PASSWORD}"

[Install]
WantedBy=multi-user.target

/etc/default/firstrun and /root/bin/firstrun-wrapper are added during installation. /etc/default/firstrun contains a password and is deleted by the firstrun-wrapper script, preventing the service from starting again after a reboot. firstrun-wrapper executes a bunch of scripts all added during installation and finishes with a reboot.

The service can be used again later to run the same setup (by adding the /etc/default/firstrun file)

So my question is. How can I run a script after the next reboot, removing the script after it has executed, and after removing the script, trigger a reboot?

It doesn't matter to me whether this uses systemd or not, and I am fine with an 'empty' (empty meaning containing no relevant/sensitive information) file being left on the system after this.

My initial thought was to modify my current service. I thought I could add another script in firstrun-wrapper that removes certain files and modifies firstrun-wrapper not to include them anymore, and execute that script through ExecStopPost, but that isn't triggered by the service finishing on its own (from what I can tell). Even if I can modify the firstrun-wrapper file while it is being executed, I understand that would be bad practice, so I am trying to avoid that.

2

You need to run crontab -e for the user who will run the script - sudo crontab -e for root or sudo -u user_name -e to edit crontab for user_name. Insert @reboot /path/to/file (NB! Don't forget the empty new line). The script itself should look like this:

#!/bin/bash
do_your_stuff
# remove from root specific crontab setting all the information about the script
sed -i '/@reboot \/path\/to\/file/d' /var/spool/cron/crontabs/root
# remove the script file itself
rm -- "$0"
# reboot the machine in 2 minutes
shutdown -r +2

To automate this process you can use Ansible. Here is an example of a simple playbook, I ran it on my localhost:

---
- hosts: localhost
  tasks:
  - name: cron job
    cron:
      name: "a job for reboot"
      special_time: reboot
      job: "/path/to/file"

First, you need to run the playbook, it updates the cron tasks for root. After reboot the script should be deleted just like the /var/spool/cron/crontabs/root file entry with @reboot string. You are free to modify the file to totally delete crontab for root is necessary.

  • Does deleting the script file itself not cause any issue whatsoever? And what will happen if the cron entry stays but the file is not there? – Tobias Feb 21 '18 at 10:07
  • I tested more simple version of the script, it works fine. If you use /etc/crontab for autostart of the script, you should add a line sed -i /@reboot/d /etc/crontab to remove the entry. Updated my answer. – M. Dm. Feb 21 '18 at 10:17
  • I want to try this out, but just to be sure I understand it correctly. I add @reboot /path/to/file to the crontab, and the sed line in the script removes that line again when running the script? – Tobias Feb 21 '18 at 12:09
  • I've added @reboot /testscript (and placed a script at /testscript) to /etc/crontab but it doesn't seem to trigger on reboot. If this is supposed to work with 16.04, what could I be doing wrong? – Tobias Feb 21 '18 at 12:51
  • Yes, sed removes the line from crontab file before telling the machine to reboot. Is your script executable? – M. Dm. Feb 21 '18 at 13:16

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.