如何拦截关机调用并运行脚本以允许或阻止关机?
Hey there! Given your scenario—your laptop has finicky hardware that needs multiple boot attempts, and you often forget to back up modified code to your USB drive—this pre-shutdown check setup is totally feasible. Below are step-by-step solutions for both Windows and Linux, the two most common desktop systems:
Windows Implementation
1. Build Your Check Script (PowerShell Example)
First, create a PowerShell script (let’s name it ShutdownCheck.ps1) that handles the core logic: checking for your USB drive, verifying code backups, and either canceling shutdown or letting it proceed.
Here’s a ready-to-adapt example:
# Check if your USB drive is connected (replace 'E:' with your actual USB drive letter) $usbDrive = Get-Volume | Where-Object { $_.DriveLetter -eq 'E:' } if (-not $usbDrive) { # Pop up a warning to insert the USB [System.Windows.MessageBox]::Show('Please insert your USB drive to back up modified code!', 'Shutdown Cancelled', [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) # Cancel the pending shutdown request shutdown /a exit } # Add your custom code backup check logic here # This example compares local code files with their USB counterparts by modified time $localCodeDir = "C:\Your\Code\Folder\Path" $usbCodeDir = "E:\Your\Backup\Code\Folder" $hasUnbackedChanges = $false Get-ChildItem -Path $localCodeDir -Recurse -File | ForEach-Object { $usbFilePath = Join-Path -Path $usbCodeDir -ChildPath $_.FullName.Substring($localCodeDir.Length) if (-not (Test-Path $usbFilePath) -or $_.LastWriteTime -gt (Get-Item $usbFilePath).LastWriteTime) { $hasUnbackedChanges = $true return } } if ($hasUnbackedChanges) { [System.Windows.MessageBox]::Show('You have unbacked code changes! Please back them up first.', 'Shutdown Cancelled', [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) shutdown /a } else { Write-Host 'All checks passed—shutdown can proceed.' }
2. Trigger the Script on Shutdown
We’ll use Task Scheduler to run this script whenever a shutdown request is made:
- Open Task Scheduler, click "Create Basic Task"
- Name it something like "Pre-Shutdown Code Backup Check", add a description if you want, then click Next
- For the trigger, select "When a specific event is logged", then Next
- Set Log to
System, Source toUser32, Event ID to1074(this ID corresponds to a system shutdown request), then Next - For the action, select "Start a program", then Next
- In "Program/script", enter
powershell.exe; in "Add arguments", enter-ExecutionPolicy Bypass -File "C:\Full\Path\To\ShutdownCheck.ps1"(replace with your script’s actual path), then Next - Check "Open the properties dialog for this task when I click Finish", then click Finish
- In the properties window:
- Go to the "Conditions" tab and uncheck "Wake the computer to run this task"
- Go to the "Settings" tab and optionally check "If the task fails, restart every X minutes" (adjust the interval as needed)
- Click OK to save
Linux Implementation
1. Build Your Check Script (Bash Example)
Create a Bash script (name it shutdown_check.sh) with similar logic—you’ll need a tool like zenity for pop-up prompts (install it first with sudo apt install zenity on Debian/Ubuntu, or equivalent for your distro).
Example script:
#!/bin/bash # Check if your USB drive is mounted (replace /mnt/usb_backup with your actual mount point) if ! mountpoint -q /mnt/usb_backup; then zenity --warning --text="Please insert and mount your USB drive to /mnt/usb_backup to back up code!" # Cancel the pending shutdown shutdown -c exit 1 fi # Check for unbacked code changes LOCAL_CODE="/home/your_username/code_directory" USB_CODE="/mnt/usb_backup/code_backup" has_unbacked=0 # Compare local and USB code directories diff -rq "$LOCAL_CODE" "$USB_CODE" | grep -q "Only in $LOCAL_CODE" if [ $? -eq 0 ]; then has_unbacked=1 fi if [ $has_unbacked -eq 1 ]; then zenity --warning --text="You have unbacked code changes! Please back them up first." shutdown -c else echo "All checks passed—shutdown can proceed." fi
Make the script executable: chmod +x shutdown_check.sh
2. Trigger the Script on Shutdown
We’ll use systemd to hook the script into the shutdown process:
- Create a systemd service file at
/etc/systemd/system/shutdown-check.servicewith this content:
[Unit] Description=Run pre-shutdown code backup check DefaultDependencies=no Before=shutdown.target reboot.target halt.target [Service] Type=oneshot ExecStart=/full/path/to/shutdown_check.sh TimeoutStartSec=0 [Install] WantedBy=shutdown.target reboot.target halt.target
- Reload systemd to pick up the new service:
sudo systemctl daemon-reload - Enable the service so it runs automatically on shutdown/reboot:
sudo systemctl enable shutdown-check.service
Quick Notes
- Don’t forget to replace placeholder paths (like USB drive letters/mount points, code directories) with your actual setup
- On Windows, if PowerShell blocks script execution, you can run
Set-ExecutionPolicy RemoteSignedin an admin PowerShell window to loosen restrictions (the script uses-ExecutionPolicy Bypassto bypass per-run checks too) - On Linux, if you don’t want graphical prompts, you can replace
zenitywith text-based alerts (likeechoto the terminal, though this only works if you’re logged in locally)
内容的提问来源于stack exchange,提问作者Karim Mtl

