1. Overview

The Linux shutdown command is a valuable utility that enables users to manage system power-offs and control various aspects of the process. One such aspect is the ability to schedule delayed shutdowns, granting users the option to automate the procedure at a specific time.

In this tutorial, we’ll explore how to check the scheduled time of a delayed shutdown in Linux.

2. Using the shutdown Schedule File

We can check the scheduled time of a delayed shutdown by examining the schedule file associated with the shutdown command.

2.1. Inspecting /run/systemd/shutdown/scheduled

On Debian, the schedule file associated with shutdown is located in the /run/systemd/shutdown directory:

$ ls /run/systemd/shutdown/
$ 

Since the directory appears empty, we can deduce that there’s no scheduled shutdown currently configured.

Let’s proceed by scheduling a shutdown for 20:30, several hours from now:

$ date
Tue 13 Jun 2023 05:24:09 PM EEST
$ sudo shutdown 20:30
Shutdown scheduled for Tue 2023-06-13 20:30:00 EEST, use 'shutdown -c' to cancel.

We’ve used the date command to show the current date and time for comparison to the scheduled power-off time.

Now, if we list the /run/systemd/shutdown directory, we notice a file named scheduled:

$ ls /run/systemd/shutdown
scheduled

By inspecting the contents of the file, we can retrieve the scheduled time for the shutdown, denoted by USEC:

$ cat /run/systemd/shutdown/scheduled
USEC=1686677400000000
WARN_WALL=1
MODE=poweroff

The scheduled time indicated by USEC is in microseconds, starting from the Unix epoch, Jan 1 1970 00:00:00 UTC. Therefore, to make the timestamp more human-readable, we can employ the date command to perform a conversion:

$ date -d @$(head -1 /run/systemd/shutdown/scheduled | cut -c 6-15)
Tue 13 Jun 2023 08:30:00 PM EEST

By using the -d option with date, we can specify the number of seconds since the Unix epoch. To achieve this, we extract the first line of the file using head -1 within a subshell. Then, we select the characters from the 6th to the 15th position on that line using the cut command. This selection excludes the USEC= characters and the trailing six zeros that represent microsecond precision.

2.2. Creating a Script

Alternatively, we can opt for a step-by-step approach, performing equivalent operations to achieve the same result via a script:

$ cat shutdowntime.sh 
#!/usr/bin/env bash
usec=$(head -1 /run/systemd/shutdown/scheduled | cut -d '=' -f 2)
sec=$((usec / 1000000))
date -d @$sec

In shutdowntime.sh, we begin by extracting the time from the scheduled file and saving it in the usec variable. This time, we achieve this by using head -1 to select the first line of the file and cut with the -d flag to specify the delimiter as the = equals sign. Also, we use the -f flag to extract the second field.

Next, we convert the usec value into seconds using arithmetic expansion and assign the result to the sec variable. Finally, the -d flag of date converts the timestamp into a format that is more easily readable.

Running the script after providing it with the necessary execute permissions gives the required result:

$ chmod u+x shutdowntime.sh 
$ ./shutdowntime.sh 
Tue 13 Jun 2023 08:30:00 PM EEST

However, if there’s no scheduled shutdown in place, the /run/systemd/shutdown/scheduled file won’t exist. In such a case, running shutdowntime.sh returns an error, followed by the timestamp of the Unix epoch:

$ sudo shutdown -c
$ ./shutdowntime.sh 
head: cannot open '/run/systemd/shutdown/scheduled' for reading: No such file or directory
Thu 01 Jan 1970 02:00:00 AM EET

Here, we first cancel the scheduled shutdown using shutdown -c and then run the script. An error occurs when the head command tries to read a non-existent file. The display also shows the date of the Unix epoch because the sec variable takes on a zero value. This in turn happens since the usec variable is an empty string.

2.3. Verifying scheduled Exists

Summarizing what we’ve discussed so far, it would be beneficial to first check for the existence of the /run/systemd/shutdown/scheduled file. If it does exist, we can then convert the timestamp within the file into a human-readable format.

To account for this, let’s modify our previous script accordingly:

$ cat shutdowntime.sh 
#!/usr/bin/env bash
if [ -f /run/systemd/shutdown/scheduled ]; then
    usec=$(head -1 /run/systemd/shutdown/scheduled | cut -d '=' -f 2)
    sec=$((usec / 1000000))
    date -d @$sec
else
    echo 'No scheduled shutdown'
fi

We use the [] token with the -f option to test for the presence of the scheduled regular file. If the file exists, we proceed to convert the timestamp within it. Otherwise, a message is displayed indicating No scheduled shutdown.

3. Using busctl

In modern Linux systems based on systemd, we can use the busctl command to examine the DBus. DBus is a message bus system that allows for inter-process communication.

3.1. Scheduled Shutdown

Another way to acquire the scheduled shutdown time is to use the get-property subcommand of busctl, and provide it with several arguments:

  • service name
  • object path
  • interface name
  • property name

In this case, we’re interested in the ScheduledShutdown property of the org.freedesktop.login1 service:

$ busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager ScheduledShutdown
(st) "poweroff" 1686677400000000

The output shows three fields delimited by space characters. In particular, the third field represents the value in microseconds since the Unix epoch. Once again, we convert this number into seconds and then use date -d to obtain a human-readable format:

$ usec=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager ScheduledShutdown | cut -d ' ' -f 3)
$ sec=$((usec / 1000000))
$ date -d @$sec
Tue 13 Jun 2023 08:30:00 PM EEST

We use cut to extract the third field from the output and save it in the usec variable. We then convert this extracted value to seconds and save it in the sec variable. Finally, we invoke the date -d command to obtain the resulting timestamp in a human-readable format.

3.2. No Scheduled Shutdown

Importantly, if there’s no scheduled shutdown, busctl shows a zero in place of the timestamp:

$ sudo shutdown -c
$ busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager ScheduledShutdown
(st) "" 0

Here, we first canceled a previously scheduled shutdown using shutdown -c and then used busctl to view the relevant timestamp.

If we were to follow the same procedure as before, the conversion would result in obtaining the Unix epoch date:

$ usec=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager ScheduledShutdown |
         cut -d ' ' -f 3)
$ sec=$((usec / 1000000))
$ date -d @$sec
Thu 01 Jan 1970 02:00:00 AM EET

Therefore, it’s better to first check that the value returned by busctl isn’t zero before proceeding with the timestamp conversion:

$ cat shutdowntime.sh 
#!/usr/bin/env bash
usec=$(busctl get-property org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager ScheduledShutdown |
       cut -d ' ' -f 3)
if [ "$usec" -ne 0 ]; then
    sec=$((usec / 1000000))
    date -d @$sec
else
    echo 'No scheduled shutdown'
fi

Now, we conduct a test to verify whether the original timestamp is non-zero. Only if the test confirms a non-zero value do we proceed with the timestamp conversion.

Finally, it’s worth noting that on older Linux systems, the delayed shutdown service was part of systemd known as systemd-shutdownd.service.

4. Conclusion

In this article, we’ve explored two different approaches for checking the scheduled time of a delayed shutdown in Linux. The first method involves inspecting the /run/systemd/shutdown/scheduled file, while the second approach uses busctl to retrieve the necessary timestamp for the scheduled shutdown.

In both cases, the timestamp is provided in microseconds since the Unix epoch. Subsequently, we convert the timestamp into seconds and transform it into a format that is easily understandable.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.