Design a timed task management tool and implement it using Shell scripts. The core goal is to implement execution once a second and ensure that tasks are asynchronous and non-blocking. The following is the detailed design of the implementation:
Tool Functions
Task registration: Supports registration of new tasks.
Task Deletion: Supports deletion of existing tasks.
Task execution: Execute tasks once per second.
Asynchronous non-blocking: The task is executed in an independent process and does not affect the main process.
Logging: The task execution results are recorded in the log file.
Script Design
#!/bin/bash # Configuration file and log file pathsCONFIG_FILE="./" LOG_FILE="./" PID_FILE="./" RELOAD_SIGNAL_FILE="./" # Initialize configuration files and signal filesif [ ! -f "$CONFIG_FILE" ]; then touch "$CONFIG_FILE" fi if [ -f "$RELOAD_SIGNAL_FILE" ]; then rm -f "$RELOAD_SIGNAL_FILE" fi # Task status tracking tabledeclare -A LAST_EXECUTION_TIMES # Timed Schedulerscheduler() { echo $$ > "$PID_FILE" echo "Scheduler starts, PID: $$" while true; do # Check if the configuration needs to be reloaded if [ -f "$RELOAD_SIGNAL_FILE" ]; then echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] Reload the configuration" >> "$LOG_FILE" LAST_EXECUTION_TIMES=() # Clear the last execution record rm -f "$RELOAD_SIGNAL_FILE" fi # Current timestamp local current_time=$(date +%s) # Dynamically load configuration files and execute tasks while IFS="=" read -r task_name interval command; do [ -z "$task_name" ] || [ -z "$interval" ] || [ -z "$command" ] && continue # Get the last execution time, if there is no record, the default is 0 local last_exec_time=${LAST_EXECUTION_TIMES[$task_name]:-0} # Determine whether the execution interval has reached if (( current_time - last_exec_time >= interval )); then ( #Installing task name to record task execution status local TASK_LOG_FILE="$task_name/$(date '+%Y-%m-%d').log" if [ ! -d "$(dirname "$TASK_LOG_FILE")" ]; then mkdir -p "$(dirname "$TASK_LOG_FILE")" fi echo "$(date +'%H:%M:%S')implementstart" >> "$TASK_LOG_FILE" eval "$command" >> "$TASK_LOG_FILE" 2>&1 echo "end" >> "$TASK_LOG_FILE" ) & LAST_EXECUTION_TIMES[$task_name]=$current_time # Update the last execution time of the task fi done < "$CONFIG_FILE" # Wait for 1 second sleep 1 done } # Stop the schedulerstop_scheduler() { if [ -f "$PID_FILE" ]; then local pid pid=$(cat "$PID_FILE") kill "$pid" && rm -f "$PID_FILE" echo "The scheduler has stopped" else echo "The scheduler is not running" fi } # Add a taskadd_task() { local task_name="$1" local interval="$2" local command="$3" if grep -q "^$task_name=" "$CONFIG_FILE"; then echo "Task '$task_name' Already exists" return 1 fi echo "$task_name=$interval=$command" >> "$CONFIG_FILE" echo "Task '$task_name' Added successfully" } # Delete the taskremove_task() { local task_name="$1" if ! grep -q "^$task_name=" "$CONFIG_FILE"; then echo "Task '$task_name' Does not exist" return 1 fi sed -i "/^$task_name=/d" "$CONFIG_FILE" echo "Task '$task_name' Deleted" } # Reload the configurationreload_scheduler() { if [ ! -f "$PID_FILE" ]; then echo "The scheduler is not running, configuration cannot be reloaded" return 1 fi touch "$RELOAD_SIGNAL_FILE" echo "Configure reload signal sent" } # Show Helpshow_help() { echo "Usage: $0 [Command] [Parameters]" echo "Order:" echo "start start scheduler" echo "stop stop scheduler" echo "reload reload configuration file" echo "add task name seconds interval command Add task to configuration file" echo "remove task name Remove task from configuration file" echo " help show help" } # Main logiccase "$1" in start) scheduler ;; stop) stop_scheduler ;; reload) reload_scheduler ;; add) add_task "$2" "$3" "$4" ;; remove) remove_task "$2" ;; help|*) show_help ;; esac
Configuration file format
Use file storage task configuration, one task per line, in the format:
Task name = seconds interval = command
For example:
task1=5=echo 'Run every 5 seconds' task2=30=date task3=10=sleep 2 && echo 'Task completed'
Start the scheduler
./ start
Add a task
./ add "task1" 5 "echo 'Hello, every 5 seconds!'"
Delete a task
./ remove "task1"
Reload the configuration
./ reload
Stop the scheduler
./ stop
At the same time, it supports manual configuration file modification tasks
Implementation principle
Task interval control: Use the associative array LAST_EXECUTION_TIMES to record the last execution time of each task.
Dynamic interval judgment: In a cycle per second, check whether the difference between the current time and the last execution time of the task reaches the set interval number of seconds.
Dynamic configuration management: The configuration file supports real-time modification, and can take effect immediately with the reload function.
Asynchronous execution: Each task executes independently of the process and does not block other tasks.
advantage
Supports custom intervals: meet the needs of different tasks execution frequencies.
Dynamic loading: Update task configuration without restarting.
High scalability: can be further optimized as needed, such as adding task priority or log cleaning capabilities.
Create a systemd service for the timer
Create a new systemd service file: You can place the service unit file in the /etc/systemd/system/ directory. Suppose we create a service called .
sudo nano /etc/systemd/system/
Edit service unit file: The following is the content template. You can modify it as needed.
[Unit] Description=Task Scheduler Service After= [Service] Type=simple User=root ExecStart=/path/to/your/ start ExecReload=/path/to/your/ reload ExecStop=/path/to/your/ stop WorkingDirectory=/path/to/working/directory Restart=always RestartSec=5 StandardOutput=journal StandardError=journal SyslogIdentifier=task-scheduler [Install] WantedBy=
Reload systemd configuration: Let systemd recognize the new service unit file.
sudo systemctl daemon-reload
Enable Service: Set the service to start automatically when the system starts.
sudo systemctl enable
Start the service: Start the task scheduler service immediately.
sudo systemctl start
Check service status: Confirm whether the service starts normally.
sudo systemctl status
Stop service:
sudo systemctl stop
Reload the configuration (if you modify the configuration file or script):
sudo systemctl reload
The service log can be viewed through the journalctl command for debugging:
sudo journalctl -u
This is the end of this article about using shell scripts to self-timed tasks. For more relevant shell timing tasks, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!