Linux first boot script

Starting a script on first boot via a systemd service

In this tutorial, we will run a script on the first boot via a systemd service. We will add the following to the Butane config from the previous scenario:

  • Add a script at /usr/local/bin/public-ipv4.sh .
  • Configure a systemd service to run the script on first boot.

Writing the script

Let’s write a simple script that uses icanhazip.com to create an issue file to display as a prelogin message on the console:

#!/bin/bash echo "Detected Public IPv4: is $(curl https://ipv4.icanhazip.com)" > \ /etc/issue.d/50_public-ipv4.issue

This could be useful in cloud environments where you might have different public and private addresses.

We will store this script into /usr/local/bin/public-ipv4.sh when we provision the machine.

Writing the systemd service

We need to call the script from the previous section by using a systemd unit. Here is one that works for what we want, which is to execute on first boot and not again:

[Unit] Before=systemd-user-sessions.service Wants=network-online.target After=network-online.target ConditionPathExists=!/var/lib/issuegen-public-ipv4 [Service] Type=oneshot ExecStart=/usr/local/bin/public-ipv4.sh ExecStartPost=/usr/bin/touch /var/lib/issuegen-public-ipv4 RemainAfterExit=yes [Install] WantedBy=multi-user.target

We will call this unit issuegen-public-ipv4.service and we will embed it into the Butane config in the next section.

Writing the Butane config and converting to Ignition

We can now create a Butane config by including the script and the systemd unit directly as inline content into the systemd/units and storage/files sections. The final Butane config, stored in services.bu , will be:

variant: fcos version: 1.4.0 systemd: units: - name: serial-getty@ttyS0.service dropins: - name: autologin-core.conf contents: | [Service] # Override Execstart in main unit ExecStart= # Add new Execstart with `-` prefix to ignore failure` ExecStart=-/usr/sbin/agetty --autologin core --noclear %I $TERM - name: issuegen-public-ipv4.service enabled: true contents: | [Unit] Before=systemd-user-sessions.service Wants=network-online.target After=network-online.target ConditionPathExists=!/var/lib/issuegen-public-ipv4 [Service] Type=oneshot ExecStart=/usr/local/bin/public-ipv4.sh ExecStartPost=/usr/bin/touch /var/lib/issuegen-public-ipv4 RemainAfterExit=yes [Install] WantedBy=multi-user.target storage: files: - path: /etc/hostname mode: 0644 contents: inline: | tutorial - path: /etc/profile.d/systemd-pager.sh mode: 0644 contents: inline: | # Tell systemd to not use a pager when printing information export SYSTEMD_PAGER=cat - path: /usr/local/bin/public-ipv4.sh mode: 0755 contents: inline: | #!/bin/bash echo "Detected Public IPv4: is $(curl https://ipv4.icanhazip.com)" > \ /etc/issue.d/50_public-ipv4.issue

And then convert to Ignition:

butane --pretty --strict services.bu --output services.ign

Testing

Just as before we will use the following to boot the instance:

# Setup the correct SELinux label to allow access to the config chcon --verbose --type svirt_home_t services.ign # Start a Fedora CoreOS virtual machine virt-install --name=fcos --vcpus=2 --ram=2048 --os-variant=fedora-coreos-stable \ --import --network=bridge=virbr0 --graphics=none \ --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=$/services.ign" \ --disk=size=20,backing_store=$/fedora-coreos.qcow2

And view on the console that the Detected Public IPv4 is shown in the console output right before you are dropped to a login prompt:

Fedora CoreOS 36.20220723.3.1 Kernel 5.18.13-200.fc36.x86_64 on an x86_64 (ttyS0) SSH host key: SHA256:YqTZ3U/ii68ApKg79keHqPAzf/PsdKzLovB53apvgXs (ECDSA) SSH host key: SHA256:4a81UJYA4p3bWDlDDTGk0DyBm7ZNdxp1CsQXiUncnPk (ED25519) SSH host key: SHA256:AEWciPbGCeMDypbP7paIE0GC3i6eRBUO4+xME4NGbQw (RSA) enp1s0: 192.168.122.109 fe80::4e18:28bb:b37f:7c61 Ignition: ran on 2022/08/21 01:27:20 UTC (this boot) Ignition: user-provided config was applied No SSH authorized keys provided by Ignition or Afterburn Detected Public IPv4: is 82.255.80.95 tutorial login: core (automatic login) Fedora CoreOS 36.20220723.3.1 [core@tutorial ~]$

And the service shows it was launched successfully:

[core@tutorial ~]$ systemctl status --full issuegen-public-ipv4.service ● issuegen-public-ipv4.service Loaded: loaded (/etc/systemd/system/issuegen-public-ipv4.service; enabled; vendor preset: enabled) Active: active (exited) since Sun 2022-08-21 01:27:29 UTC; 2min 11s ago Process: 1646 ExecStart=/usr/local/bin/public-ipv4.sh (code=exited, status=0/SUCCESS) Process: 1677 ExecStartPost=/usr/bin/touch /var/lib/issuegen-public-ipv4 (code=exited, status=0/SUCCESS) Main PID: 1646 (code=exited, status=0/SUCCESS) CPU: 42ms Aug 21 01:27:29 tutorial systemd[1]: Starting issuegen-public-ipv4.service. Aug 21 01:27:29 tutorial public-ipv4.sh[1647]: % Total % Received % Xferd Average Speed Time Time Time Current Aug 21 01:27:29 tutorial public-ipv4.sh[1647]: Dload Upload Total Spent Left Speed Aug 21 01:27:29 tutorial public-ipv4.sh[1647]: [237B blob data] Aug 21 01:27:29 tutorial systemd[1]: Finished issuegen-public-ipv4.service.

Cleanup

Now let’s take down the instance for the next test. First, disconnect from the serial console by pressing CTRL + ] and then destroy the machine:

virsh destroy fcos virsh undefine --remove-all-storage fcos

You may now proceed with the next tutorial.

Читайте также:  Умный дом linux сервер умного дома

All Fedora Documentation content available under CC BY-SA 4.0 or, when specifically noted, under another accepted free and open content license.

Fedora Logo

Last build: 2023-07-17 04:50:08 UTC | Last content update: 2022-09-15

Источник

Run a Script on Startup in Linux

announcement - icon

The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.

To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.

Connect your cluster and start monitoring your K8s costs right away:

1. Overview

In this quick tutorial, we’ll explore different options for executing a script on startup in Linux. This comes in handy in plenty of situations, such as if we want to start a server application automatically.

2. Solutions

Without further ado, let’s create a simple script to execute:

#!/bin/sh echo "Last reboot time: $(date)" > /etc/motd

This piece of code sets the message of the day to be the last reboot time, so that each user can see it after their first login.

Then we’ll save our file and make it executable:

Now that our script is ready, let’s see how to schedule its execution.

2.1. Using cron

Let’s begin with the easiest solution, which involves using cron. In order to do this, we need to edit our crontab file:

Читайте также:  Linux file names with spaces

Here we’ll add a line using the @reboot expression, which will execute our code once at startup:

@reboot sh /home/ec2-user/reboot_message.sh

This solution is quick and clean, since we don’t have to deal with additional configuration, but not every version of cron supports @reboot.

2.2. Using rc.local

Now let’s consider another solution that takes advantage of the /etc/rc.d/rc.local file. Since this file already runs at startup, we can append a line that invokes our script:

sh /home/ec2-user/reboot_message.sh

In order for this to work, we need to ensure that the rc.local file itself is executable:

2.3. Using init.d

Similar to the previous solution, the /etc/init.d folder contains lifecycle executables of the services managed by the system. We can also add our own by creating an LSB-compliant wrapper that starts our service:

#! /bin/sh # chkconfig: 345 99 10 case "$1" in start) # Executes our script sudo sh /home/ec2-user/reboot_message.sh ;; *) ;; esac exit 0 

This wrapper will launch our code when it’s invoked with the start argument. However, we must include a line with the chkconfig configuration, which contains the service runlevel and the start/stop priority.

After placing the wrapper in the init.d folder, we need to register our service for startup execution:

$ chkconfig --add service_wrapper.sh

Since the chkconfig command isn’t available on Debian systems, update-rc.d can be used as an alternative there:

$ update-rc.d service_wrapper.sh defaults

2.4. Using systemd

Finally, let’s see how to run a script with systemd. Similar to init.d, we need to create a service descriptor, called a unit file, under /etc/systemd/system:

[Unit] Description=Reboot message systemd service. [Service] Type=simple ExecStart=/bin/bash /home/ec2-user/reboot_message.sh [Install] WantedBy=multi-user.target 

The file is organized into different sections:

  • Unit – contains general metadata, like a human-readable description
  • Service – describes the process and daemonizing behavior, along with the command to start the service
  • Install – enables the service to run at startup using the folder specified in WantedBy to handle dependencies
Читайте также:  Pdf to xls linux

Next, we’ll need to set the file permissions to 644, and enable our service by using systemctl:

$ chmod 644 /etc/systemd/system/reboot_message.service $ systemctl enable reboot_message.service

One thing to keep in mind is that, although many major distributions support systemd, it’s not always available.

3. Conclusion

In this article, we took a look at different ways of executing a script at startup in Linux. Each one of them has its pros and cons, but generally speaking, systemd and cron should be preferred when available. Consequently, rc.local and init.d should be used as fallbacks.

Источник

Оцените статью
Adblock
detector