如何定时启停进程并基于文件内容条件终止进程?
Fixing Your Scheduled Process Start/Stop + File Monitoring Logic
Let's walk through why your current approach isn't working, then build a solid solution that handles both scheduled timing and conditional termination based on file content.
Why Your Original Script Fails
Your line TASK_PID=$! kill $TASK_PID | at 5:00 has a critical flaw:
- The
$!variable only captures the PID of the last background process run in your current shell session. When you useat, you're submitting a task to run in an entirely separate shell later—so$!here doesn't refer to the process you'll start at 8:00. In fact, it's probably empty, sinceatruns in the foreground to submit the task and exits immediately.
Step 1: Scheduled Start + Scheduled Stop (Working Version)
To make this work, we need to save the PID of the 8:00 process to a file, then have the 17:00 task read that file to kill the process.
Schedule the Startup (8:00 AM)
# Submit a task to start your process at 8:00, save its PID to a file echo " # Start your command in the background, redirect logs if needed your_command_here > /var/log/my_task_output.log 2>&1 & # Save the PID to a temporary file echo \$! > /tmp/my_task.pid " | at 8:00
- Note the escaped
\$!: this ensures theattask's shell (not your current shell) captures the PID of the backgrounded process. - Adjust the log path to a location your user has write access to.
Schedule the Shutdown (5:00 PM)
# Submit a task to kill the process at 17:00, clean up the PID file echo " if [ -f /tmp/my_task.pid ]; then # Read the PID and check if the process is still running TASK_PID=$(cat /tmp/my_task.pid) if kill -0 \$TASK_PID 2>/dev/null; then kill \$TASK_PID echo \"Killed process \$TASK_PID at 17:00\" >> /var/log/my_task_output.log fi # Clean up the PID file regardless rm /tmp/my_task.pid fi " | at 17:00
kill -0checks if the process exists without sending a kill signal, avoiding unnecessary errors.- We add a log entry to track when the scheduled shutdown runs.
Step 2: Add Conditional Termination via File Monitoring
Now let's add the logic to kill the process early if any of your three conditions appear in the last line of a target file. We'll tie this to the startup task so monitoring starts when your process does.
Update the 8:00 startup command to include the monitor:
echo " # Start your main process and save its PID your_command_here > /var/log/my_task_output.log 2>&1 & MAIN_PID=\$! echo \$MAIN_PID > /tmp/my_task.pid # Start the file monitoring script in the background tail -F /path/to/your/monitored_file.log | while read -r line; do # Check if the line matches any of your conditions if echo \"\$line\" | grep -qE 'Condition1|Condition2|Condition3'; then # Kill the main process if condition is met if kill -0 \$MAIN_PID 2>/dev/null; then kill \$MAIN_PID echo \"Killed process \$MAIN_PID early due to condition: \$line\" >> /var/log/my_task_output.log fi # Clean up PID file and exit the monitor rm /tmp/my_task.pid exit 0 fi done & MONITOR_PID=\$! # Ensure the monitor exits when the main process does (prevents zombie monitors) wait \$MAIN_PID kill \$MONITOR_PID 2>/dev/null " | at 8:00
Key details here:
tail -F(not-f) handles log rotation gracefully—if the monitored file is replaced (e.g., by logrotate),tailwill reattach to the new file.grep -qEuses extended regex to match any of your three conditions quietly (no output, just exit code).- The
wait $MAIN_PIDline ensures the monitor process is killed automatically if the main process ends on its own, so you don't leave orphaned monitoring scripts running.
Final Notes
- Permissions: Make sure the user running
athas write access to/tmp, your log directories, and permission to kill the process (usually the same user that starts it). - Testing: Test the startup/monitor logic manually first (without
at) to make sure it works before scheduling it. - Edge Cases: If your process might spawn child processes, use
kill -TERM $MAIN_PIDto send a termination signal, orkill -9only as a last resort (it doesn't let processes clean up).
内容的提问来源于stack exchange,提问作者Juno
相关产品推荐
相关产品推荐

