Practical Example: Running ping, df, and systemctl

🏷️ Operating System and System Operations / Shell Commands with Subprocess

🧭 Context Introduction

When working with servers and systems, you'll frequently need to run shell commands from within Python scripts. Whether it's checking if a remote host is reachable, monitoring disk space, or managing services, the subprocess module is your gateway to executing system commands programmatically. This guide walks through three real-world examples that engineers encounter daily: ping, df, and systemctl.


βš™οΈ Why Use Subprocess Instead of os.system?

Before diving into examples, it's important to understand why subprocess is preferred over the older os.system approach:

  • subprocess gives you full control over input, output, and error streams
  • It returns exit codes that you can check programmatically
  • It handles arguments safely without shell injection risks
  • You can capture command output as strings for further processing

πŸ•΅οΈ Example 1: Running ping to Check Network Connectivity

The ping command tests whether a remote host is reachable over the network. In automation scripts, you might use this to verify that a server is online before deploying updates or running backups.

How it works: - You call subprocess.run() with the ping command and target IP or hostname - On Linux, you typically use the -c flag to limit the number of packets (e.g., -c 4 for four pings) - The command returns a CompletedProcess object containing the exit code and output - An exit code of 0 means the host is reachable; any other code indicates failure

Practical use case: - A monitoring script that pings a list of servers every minute - A deployment script that waits for a server to come back online after a reboot - A network troubleshooting tool that logs ping results over time

Key considerations: - Use capture_output=True to store the command's stdout and stderr - Set text=True to get output as strings instead of bytes - Check returncode to determine success or failure


πŸ“Š Example 2: Running df to Check Disk Usage

The df command reports filesystem disk space usage. Engineers use this constantly to monitor storage capacity, identify full disks, and trigger alerts before space runs out.

How it works: - You call subprocess.run() with the df command and useful flags like -h (human-readable) or -T (filesystem type) - The output is a table showing mount points, total size, used space, available space, and usage percentage - You can parse this output to extract specific values for monitoring or alerting

Practical use case: - A daily cron job that checks disk usage and sends warnings if any partition exceeds 80% - A deployment script that verifies enough free space exists before copying large files - A dashboard that collects disk metrics from multiple servers

Key considerations: - Use -h flag to get sizes in KB, MB, or GB instead of raw bytes - Parse the output line by line, skipping the header row - Convert percentage strings to integers for comparison logic


πŸ› οΈ Example 3: Running systemctl to Manage Services

The systemctl command controls systemd services on modern Linux distributions. Engineers use it to start, stop, restart, enable, or check the status of services.

How it works: - You call subprocess.run() with systemctl followed by an action and service name - Common actions include status, start, stop, restart, and enable - The status action returns detailed information about whether a service is active, enabled, or failed

Practical use case: - A deployment script that restarts a web application after updating its code - A health check script that verifies critical services like nginx or sshd are running - A recovery script that attempts to restart failed services automatically

Key considerations: - Use systemctl is-active for a simple yes/no check on service status - Use systemctl is-enabled to check if a service starts on boot - Always handle permission errors gracefully (some commands require sudo)


πŸ” Comparison Table: Command Characteristics

Feature ping df systemctl
Purpose Network connectivity test Disk space reporting Service management
Exit code meaning 0 = reachable, 1 = unreachable 0 = success, non-zero = error 0 = active, 3 = inactive
Output format Text summary with statistics Tabular data with columns Structured text with details
Common flags -c (count), -W (timeout) -h (human-readable), -T (type) status, start, stop
Parsing complexity Low (check exit code) Medium (parse table rows) Low to medium (check status line)

πŸ§ͺ Putting It All Together: A Simple System Health Script

Imagine you want to write a Python script that performs three checks on a server:

  1. Ping a remote database server to ensure it's reachable
  2. Check disk usage on the root partition to avoid running out of space
  3. Verify that the nginx web server service is running

Script flow: - First, run ping -c 4 192.168.1.100 and check the return code - If ping fails, log an error and exit early - Next, run df -h / and parse the output to find the usage percentage - If usage exceeds 90%, trigger a warning - Finally, run systemctl is-active nginx and check if the output is "active" - If nginx is inactive, attempt to restart it with systemctl restart nginx

Error handling tips: - Wrap each subprocess call in a try/except block to catch FileNotFoundError (command missing) or CalledProcessError - Use stderr capture to log any error messages from the commands themselves - Set a timeout for ping to prevent the script from hanging on unreachable hosts


βœ… Best Practices for Running Shell Commands in Python

  • Always use subprocess.run() instead of os.system() for better control and safety
  • Pass commands as lists (e.g., ["ping", "-c", "4", "google.com"]) to avoid shell injection
  • Capture output with capture_output=True and text=True for easy string handling
  • Check return codes explicitly rather than assuming success
  • Set timeouts for network commands to prevent indefinite hangs
  • Handle missing commands gracefully with try/except
  • Log both stdout and stderr for debugging failed commands

πŸš€ Next Steps

Now that you've seen how to run ping, df, and systemctl from Python, try building your own health check script that combines all three. Start simpleβ€”just print the resultsβ€”then gradually add logic for alerts, retries, and logging. As you grow more comfortable, explore other useful commands like ps (process list), netstat (network connections), and journalctl (system logs) to expand your automation toolkit.


This section shows how to run common system commands from Python using the subprocess module.


πŸ–₯️ Example 1: Running a simple ping command

This example runs a single ping to check if a host is reachable.

import subprocess

result = subprocess.run(["ping", "-c", "1", "8.8.8.8"], capture_output=True, text=True)
print(result.stdout)

πŸ“€ Output: PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=12.3 ms


πŸ’Ύ Example 2: Checking disk space with df

This example runs the df command to show available disk space in human-readable format.

import subprocess

result = subprocess.run(["df", "-h"], capture_output=True, text=True)
print(result.stdout)

πŸ“€ Output: Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 20G 30G 40% /


βš™οΈ Example 3: Checking a service status with systemctl

This example checks whether the ssh service is active using systemctl.

import subprocess

result = subprocess.run(["systemctl", "is-active", "ssh"], capture_output=True, text=True)
print(result.stdout.strip())

πŸ“€ Output: active


πŸ”„ Example 4: Running ping with a timeout and checking return code

This example runs ping with a timeout and checks if the command succeeded or failed.

import subprocess

result = subprocess.run(["ping", "-c", "3", "google.com"], capture_output=True, text=True, timeout=10)
if result.returncode == 0:
    print("Ping successful")
else:
    print("Ping failed")

πŸ“€ Output: Ping successful


πŸ“Š Example 5: Combining df output with error handling

This example runs df on a specific mount point and handles errors if the path does not exist.

import subprocess

try:
    result = subprocess.run(["df", "-h", "/nonexistent"], capture_output=True, text=True, check=True)
    print(result.stdout)
except subprocess.CalledProcessError as e:
    print(f"Command failed with error: {e.stderr.strip()}")

πŸ“€ Output: Command failed with error: df: /nonexistent: No such file or directory


πŸ“‹ Comparison Table

Command Purpose Common Options Typical Use Case
ping Test network connectivity -c (count), -w (timeout) Check if a remote host is reachable
df Show disk space usage -h (human-readable), -T (filesystem type) Monitor available disk space
systemctl Control system services is-active, status, start, stop Check or manage service states

🧭 Context Introduction

When working with servers and systems, you'll frequently need to run shell commands from within Python scripts. Whether it's checking if a remote host is reachable, monitoring disk space, or managing services, the subprocess module is your gateway to executing system commands programmatically. This guide walks through three real-world examples that engineers encounter daily: ping, df, and systemctl.


βš™οΈ Why Use Subprocess Instead of os.system?

Before diving into examples, it's important to understand why subprocess is preferred over the older os.system approach:

  • subprocess gives you full control over input, output, and error streams
  • It returns exit codes that you can check programmatically
  • It handles arguments safely without shell injection risks
  • You can capture command output as strings for further processing

πŸ•΅οΈ Example 1: Running ping to Check Network Connectivity

The ping command tests whether a remote host is reachable over the network. In automation scripts, you might use this to verify that a server is online before deploying updates or running backups.

How it works: - You call subprocess.run() with the ping command and target IP or hostname - On Linux, you typically use the -c flag to limit the number of packets (e.g., -c 4 for four pings) - The command returns a CompletedProcess object containing the exit code and output - An exit code of 0 means the host is reachable; any other code indicates failure

Practical use case: - A monitoring script that pings a list of servers every minute - A deployment script that waits for a server to come back online after a reboot - A network troubleshooting tool that logs ping results over time

Key considerations: - Use capture_output=True to store the command's stdout and stderr - Set text=True to get output as strings instead of bytes - Check returncode to determine success or failure


πŸ“Š Example 2: Running df to Check Disk Usage

The df command reports filesystem disk space usage. Engineers use this constantly to monitor storage capacity, identify full disks, and trigger alerts before space runs out.

How it works: - You call subprocess.run() with the df command and useful flags like -h (human-readable) or -T (filesystem type) - The output is a table showing mount points, total size, used space, available space, and usage percentage - You can parse this output to extract specific values for monitoring or alerting

Practical use case: - A daily cron job that checks disk usage and sends warnings if any partition exceeds 80% - A deployment script that verifies enough free space exists before copying large files - A dashboard that collects disk metrics from multiple servers

Key considerations: - Use -h flag to get sizes in KB, MB, or GB instead of raw bytes - Parse the output line by line, skipping the header row - Convert percentage strings to integers for comparison logic


πŸ› οΈ Example 3: Running systemctl to Manage Services

The systemctl command controls systemd services on modern Linux distributions. Engineers use it to start, stop, restart, enable, or check the status of services.

How it works: - You call subprocess.run() with systemctl followed by an action and service name - Common actions include status, start, stop, restart, and enable - The status action returns detailed information about whether a service is active, enabled, or failed

Practical use case: - A deployment script that restarts a web application after updating its code - A health check script that verifies critical services like nginx or sshd are running - A recovery script that attempts to restart failed services automatically

Key considerations: - Use systemctl is-active for a simple yes/no check on service status - Use systemctl is-enabled to check if a service starts on boot - Always handle permission errors gracefully (some commands require sudo)


πŸ” Comparison Table: Command Characteristics

Feature ping df systemctl
Purpose Network connectivity test Disk space reporting Service management
Exit code meaning 0 = reachable, 1 = unreachable 0 = success, non-zero = error 0 = active, 3 = inactive
Output format Text summary with statistics Tabular data with columns Structured text with details
Common flags -c (count), -W (timeout) -h (human-readable), -T (type) status, start, stop
Parsing complexity Low (check exit code) Medium (parse table rows) Low to medium (check status line)

πŸ§ͺ Putting It All Together: A Simple System Health Script

Imagine you want to write a Python script that performs three checks on a server:

  1. Ping a remote database server to ensure it's reachable
  2. Check disk usage on the root partition to avoid running out of space
  3. Verify that the nginx web server service is running

Script flow: - First, run ping -c 4 192.168.1.100 and check the return code - If ping fails, log an error and exit early - Next, run df -h / and parse the output to find the usage percentage - If usage exceeds 90%, trigger a warning - Finally, run systemctl is-active nginx and check if the output is "active" - If nginx is inactive, attempt to restart it with systemctl restart nginx

Error handling tips: - Wrap each subprocess call in a try/except block to catch FileNotFoundError (command missing) or CalledProcessError - Use stderr capture to log any error messages from the commands themselves - Set a timeout for ping to prevent the script from hanging on unreachable hosts


βœ… Best Practices for Running Shell Commands in Python

  • Always use subprocess.run() instead of os.system() for better control and safety
  • Pass commands as lists (e.g., ["ping", "-c", "4", "google.com"]) to avoid shell injection
  • Capture output with capture_output=True and text=True for easy string handling
  • Check return codes explicitly rather than assuming success
  • Set timeouts for network commands to prevent indefinite hangs
  • Handle missing commands gracefully with try/except
  • Log both stdout and stderr for debugging failed commands

πŸš€ Next Steps

Now that you've seen how to run ping, df, and systemctl from Python, try building your own health check script that combines all three. Start simpleβ€”just print the resultsβ€”then gradually add logic for alerts, retries, and logging. As you grow more comfortable, explore other useful commands like ps (process list), netstat (network connections), and journalctl (system logs) to expand your automation toolkit.

Interactive Views

You are currently in πŸ“š All-in-One mode. Use the tabs at the top to switch to πŸ“– Theory Only or πŸ’» Code Only views.

This section shows how to run common system commands from Python using the subprocess module.


πŸ–₯️ Example 1: Running a simple ping command

This example runs a single ping to check if a host is reachable.

import subprocess

result = subprocess.run(["ping", "-c", "1", "8.8.8.8"], capture_output=True, text=True)
print(result.stdout)

πŸ“€ Output: PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=12.3 ms


πŸ’Ύ Example 2: Checking disk space with df

This example runs the df command to show available disk space in human-readable format.

import subprocess

result = subprocess.run(["df", "-h"], capture_output=True, text=True)
print(result.stdout)

πŸ“€ Output: Filesystem Size Used Avail Use% Mounted on /dev/sda1 50G 20G 30G 40% /


βš™οΈ Example 3: Checking a service status with systemctl

This example checks whether the ssh service is active using systemctl.

import subprocess

result = subprocess.run(["systemctl", "is-active", "ssh"], capture_output=True, text=True)
print(result.stdout.strip())

πŸ“€ Output: active


πŸ”„ Example 4: Running ping with a timeout and checking return code

This example runs ping with a timeout and checks if the command succeeded or failed.

import subprocess

result = subprocess.run(["ping", "-c", "3", "google.com"], capture_output=True, text=True, timeout=10)
if result.returncode == 0:
    print("Ping successful")
else:
    print("Ping failed")

πŸ“€ Output: Ping successful


πŸ“Š Example 5: Combining df output with error handling

This example runs df on a specific mount point and handles errors if the path does not exist.

import subprocess

try:
    result = subprocess.run(["df", "-h", "/nonexistent"], capture_output=True, text=True, check=True)
    print(result.stdout)
except subprocess.CalledProcessError as e:
    print(f"Command failed with error: {e.stderr.strip()}")

πŸ“€ Output: Command failed with error: df: /nonexistent: No such file or directory


πŸ“‹ Comparison Table

Command Purpose Common Options Typical Use Case
ping Test network connectivity -c (count), -w (timeout) Check if a remote host is reachable
df Show disk space usage -h (human-readable), -T (filesystem type) Monitor available disk space
systemctl Control system services is-active, status, start, stop Check or manage service states