Run a script only at the very first boot

64,257

Solution 1

No. But you might want to place your script in /etc/init.d/script, and self-delete it:

#!/bin/bash

echo "Bump! I'm your first-boot script."

# Delete me
rm $0

Solution 2

Combining the first two answers Assuming you name your script /usr/local/bin/firstboot.sh put it at the end of /etc/rc.local (this scripts runs on every boot) the scripts goes like this

Update 2022: Put the script in crontab like this

@reboot /usr/local/bin/firstboot.sh
#!/bin/bash

FLAG="/var/log/firstboot.log"
if [[ ! -f $FLAG ]]; then
   #Put here your initialization sentences
   echo "This is the first boot"
   
   #the next line creates an empty file so it won't run the next boot
   touch "$FLAG"
else
   echo "Do nothing"
fi

Solution 3

Create a tracking file when the script runs. If the file already exists, exit the script.

Solution 4

In my case, it was building a custom system and I had to refuse to use cloud-init and placing a script under /etc/init.d/script didn't work - so I used systemd.

FILE /etc/systemd/system/firstboot.service

[Unit]
Description=One time boot script
[Service]
Type=simple
ExecStart=/firstboot.sh
[Install]
WantedBy=multi-user.target 

and

FILE /firstboot.sh

#!/bin/bash 
SOME COMMANDS YOU WANT TO EXECUTE
systemctl disable firstboot.service 
rm -rf /etc/systemd/system/firstboot.service
rm -f /firstboot.sh

Then enable

(sudo) chmod +x /firstboot.sh
(sudo) systemctl enable firstboot.service

This one works just fine for me.

Solution 5

I'm surprised at the results I'm seeing for searching for a well-defined and supported Ubuntu "first boot" hook. Seems like the Red Hat / Fedora / CentOS crowd has had this nailed for over a decade. The closest Ubuntu equivalent seems to be oem-config-firstboot.

The idea of simply performing an rm $0 will work. But, technically there are some interesting semantics involved. Unlike most other script interpreters under Unix a shell script is read and processed one line/statement at a time. If you unlink (rm) the file out from under it then that the instance of the shell that's processing that script is now working with an anonymous file (any file that's open but unlinked).

Consider a file like this:

#!/bin/bash
rm $0
echo "I've removed myself: $0"
ls -l $0
cat <<COMMENTARY
   This is a test.
   I'm still here, because the "here" doc is being fed to 'cat'
   via the anonymous file through the open file descriptor.
   But I cannot be re-exec'd
COMMENTARY
exec $0

If you save that to something like rmself.sh and (hard) link that to something like tst then running ./tst should show something like this as output:

$ ./tst 
I've removed myself: ./tst
ls: ./tst: No such file or directory
   This is a test.
   I'm still here, because the "here" doc is being fed to 'cat'
   via the anonymous file through the open file descriptor.
   But I cannot be re-exec'd
./tst: line 11: /home/jimd/bin/tst: No such file or directory
./tst: line 11: exec: /home/jimd/bin/tst: cannot execute: No such file or directory

Now there are some odd possible corner cases with regards to symlinks and cases where the script was invoked as a bare name (forcing the shell to search the $PATH for the script.

But it seems that bash (at least in version 3.2) prepends $0 with the path if it searched the path and otherwise leaves $0 set to whatever relative or absolute path was used to invoke the script. It doesn't seem to do any normalization or resolution relative paths nor symlinks.

Probably the cleanest "firstboot" for Ubuntu would be to create a small package (.deb) containing a script to be placed in /etc/init.d/firstboot and a post-install script that uses update-rc.d to link that into runlevel 1 (/etc/rc1.d) (using a command like: update-rc.d firstboot defaults) ... and then have the last line perform a deactivation or delete using something like: update-rc.d firstboot disable

Here's a link to the Debian update-rc.d HOWTO

Share:
64,257

Related videos on Youtube

Roberto Aloi
Author by

Roberto Aloi

Because of my academic career, I’m interested in software engineering, human - computer interaction, user interfaces, graphics, databases, web applications and more. As the final thesis for my Bachelor's degree, I implemented a garbage collector for a Java Virtual Machine (named Juice) targeted to embedded systems with real time requirements. As the final thesis for my Master's degree, I designed an access control mechanism for the Content Management System Joomla (www.joomla.org). It was successfully used for an e-learning solution. I spent my last years discovering the Erlang language and getting addicted to it.

Updated on September 18, 2022

Comments

  • Roberto Aloi
    Roberto Aloi over 1 year

    Is there an idiomatic way in Ubuntu to run a script only the first time a machine is booted? (EC2).

  • Andrejs Cainikovs
    Andrejs Cainikovs almost 12 years
    Please note, $0 is bash-specific (version >= 3). For compatibility purpose you can provide script file name instead, making this less generic: rm /etc/init.d/script
  • msanford
    msanford about 10 years
    While it might not seem so at first glance, this may be a better solution than deleting the script as it retains the possibility to trigger it again, should you ever want to.
  • Jim Dennis
    Jim Dennis about 9 years
    $0 is NOT bash specific and it has been supported for far longer than bash 3.x has been around (and it's supported in Bourne, Korn, zsh and others). The sticking point is whether $0 contains a full or relative path specification. Here's a link to a reliable way of getting the full path if you need it: stackoverflow.com/questions/4774054/…
  • mrossi
    mrossi over 7 years
    This is not necessarily working with sysmtemd. I need to add a sleep 20 to make sure it is the last script run.
  • JohnDavid
    JohnDavid over 5 years
    If you name it /etc/rc.local/99-firstboot.sh it should run last.
  • WinEunuuchs2Unix
    WinEunuuchs2Unix about 3 years
    You just need to add the directory names and filenames for the files you created.
  • Adam Krawczyk
    Adam Krawczyk about 3 years
    note that commands I've posted are echo "sth" > filename. The output of echo command is directed to a specific file with filename (if the file doesn't exist then it's created)
  • Adam Krawczyk
    Adam Krawczyk about 3 years
    Okay for clarity changed this. :)