safe_sleep.sh Bash script from the GitHub Actions runner, which gained viral attention for its inefficient design.SECONDS variable, causing high CPU utilization and inaccurate sleep durations (between 4 and 5 seconds for a 5-second request).sleep binary, which efficiently instructs the kernel to suspend the process.sleep is unavailable, it falls back to a clever ping command trick to introduce delay.ping is also unsuitable, it tries to use the Bash read -t built-in with a timeout, reading from various file descriptors.ping behavior and the potential for floating-point issues with sleep arguments, suggesting robust input validation and consistent Bashisms.
safe_sleep.sh Script [00:00:00]The video addresses the safe_sleep.sh Bash script, part of the GitHub Actions runner repository, which recently went viral. The speaker, a Bash expert, chose to wait for the initial controversy to subside before providing a technical post-mortem analysis of the script's evolution.
safe_sleep.sh Script [00:01:31]The initial version of safe_sleep.sh was a very simple Bash script designed to pause execution for a specified duration.
Code Structure [00:01:31]
SECONDS=0: Initializes a variable named SECONDS.while [[ $SECONDS != $1 ]]; do :; done: A loop that continues as long as SECONDS is not equal to the first command-line argument ($1).do :; done block uses the null command (:) which does nothing and always succeeds, meaning the loop itself performs no operation other than checking the condition.Understanding the SECONDS Variable [00:03:20]
SECONDS is a special variable in Bash that expands to the number of seconds since the shell's invocation.SECONDS is assigned a value (e.g., SECONDS=0), subsequent references will return the number of seconds elapsed since that assignment, providing a simple timer.SECONDS is 1 second, meaning it updates every full second.SECONDS is unset, it loses its special properties, even if subsequently reset. (Not directly relevant to this script but an important Bash detail).The "Busy Wait" Problem [00:06:02]
SECONDS variable, despite the null command, keeps the CPU active. This is known as "busy waiting."echo statement.
Measuring Performance with time [00:07:02]
time command provides insights into a program's execution:real time: Wall clock time (total elapsed time).user time: Time spent in user space (CPU-bound work like calculations).sys time: Time spent in system space (kernel-level work like I/O operations on behalf of the process).safe_sleep.sh script showed almost all execution time being user time, indicating CPU-intensive busy-waiting instead of efficient kernel-level sleeping.
sleep command [00:10:19]sleep command efficiently utilizes the kernel to suspend the process, resulting in minimal user and sys time.
user time can exceed the real (wall clock) time, as each process consumes its own CPU time.The Problem with == (Equality Check) [00:13:02]
[[ $SECONDS != $1 ]] checks for strict inequality.SECONDS variable might increment past the target value (e.g., from 4 to 6, skipping 5). In such a scenario, the != condition would always be true, leading to an infinite loop.-le or -lt) to ensure the loop terminates once the SECONDS variable reaches or exceeds the target.safe_sleep.sh Script (Current Version) [00:17:41]The updated safe_sleep.sh script adopts a more robust, multi-tiered approach to achieve reliable sleep functionality, prioritizing efficient kernel-level operations.
Prioritizing sleep Binary [00:18:02]
sleep binary using command -v sleep and [ -x ... ].sleep "$duration" and exits. This is the most efficient method as it offloads the timing responsibility to the kernel.
sleep utility is POSIX-specified to suspend execution for at least the integral number of seconds specified.
Fallback to ping Command [00:20:40]
sleep is not found, the script tries to use the ping command as a fallback.ping -c $((duration + 1)) 127.0.0.1 >/dev/null.ping sending one packet per second by default and -c specifying the count. To sleep for N seconds, N+1 pings are sent, effectively resulting in N 1-second delays between packets.ping (especially -c for count and default interval) is not consistent across all Unix-like systems. Some systems (e.g., Illumos) treat -c as a traffic class and ping only once by default, causing this fallback to fail or behave unexpectedly.ping command output is redirected to /dev/null to suppress its normal output.Fallback to read -t (Bash Built-in) [00:22:59]
ping is not suitable, the script attempts to use the Bash built-in read command with the -t (timeout) option.BASH_VERSION is set and if read is available.read from it with a specified timeout (read -t "$duration" -u "$FD").The Ultimate Fallback: Busy Wait [00:26:04]
SECONDS variable: while [[ $SECONDS -lt $duration ]]; do :; done.-lt (less than) comparison to correctly terminate the loop, addressing the unbounded loop bug of the original script.The speaker offers several critiques and suggestions for improving the script's robustness and maintainability.
Input Validation [00:27:59]
sleep, ping) or arithmetic expressions can fail or behave unexpectedly (e.g., ping -c $((hello + 1)) evaluates "hello" to 0).Fractional Sleep and Portability Concerns [00:31:18]
sleep binaries often support fractional seconds (e.g., sleep 2.5), the POSIX specification for sleep only guarantees integral seconds.sleep might lead to inconsistent behavior on different systems.ping: The arithmetic expression duration + 1 in the ping fallback performs integer arithmetic. If duration were a floating-point number (e.g., 2.5), Bash would truncate it to an integer [2], leading to an incorrect ping count.Code Refactoring and Bashisms [00:32:28]
[ ]) and double ([[ ]]) square bracket notations. While both work in Bash, consistent use of [[ ]] (a Bashism) is generally preferred for Bash scripts due to enhanced features and reduced word-splitting issues.read -t checks: The three separate if blocks for file descriptors 0, 1, and 2 can be refactored into a for loop, making the code more concise and easier to maintain.sleep "$duration") helps prevent unintended word splitting and globbing.ping Command Inconsistencies Across Systems [00:37:38]
ping behavior is not uniform across all Unix-like operating systems.ping -c N behaves as expected (N pings, N-1 second delays).ping by default pings only once, and -c specifies a "traffic class" instead of a count, immediately returning "localhost is alive".
ping fallback in the safe_sleep.sh script would not function as intended on such systems, leading to a much shorter sleep or immediate exit.The speaker summarizes the review by showcasing his refactored version of the script incorporating the suggested improvements, emphasizing educational value.
[[ ]] notation, and a consolidated loop for read -t checks.