如何在Linux關機時執行命令

    Linux和Unix系統一直很容易在啓動時執行命令,只需要將你的命令添加到 /etc/rc.local 文件中。但事實證明,在關機時運行命令有點複雜。

    你爲什麼想要在計算機關閉時運行命令呢?也許你想從數據庫去註冊一個機器或服務,也許你想將數據從一個易失性存儲系統複製到一個永久的位置(比如將內存中的數據寫入到硬盤中去),或者想要你的電腦在它關機前在它的Twitter賬戶上發佈"#RIP me!"

    我需要澄清一點,我說的是所謂的“一次性”命令而不是停止守護進程。儘管把他們想象成一樣是誘人的。如果你熟悉SysVinit,你可能會想“哦,我能直接創建一個Kill腳本”。例如,當你的系統在運行級別3退出時/ etc / rc.d/rc3.d/k99runmycommandatshutdown會調用。畢竟這就是/etc/init.d/中的腳本如何停止的。

    這是一個膩害的猜測,然而事實證明這是錯誤的。SysVinit並不盲目運行Kill腳本。相反,它 (RedHat 6)會在 /var/lock/subsys/service_name (此處的service_name假設爲runmycommandatshutdown)中查找可執行的相關命令。所以你可能會在讓系統將你的腳本當作普通服務上遇到一些麻煩。下面的腳本給出了一個例子:

#!/bin/sh
# chkconfig: 2345 20 80
# description: An example init script to run a command at shutdown 
# runmycommandatshutdown runs a command at shutdown. Very creative. 

LOCKFILE=/var/lock/subsys/
start(){
    # Touch our lock file so that stopping will work correctly
    touch ${LOCKFILE}
    } 
stop(){
    # Remove our lock file
    rm ${LOCKFILE}
    # Run that command that we wanted to run
    mycommand
    } 
   
case "$1" in
    start) start;;
    stop) stop;;
    *)
        echo $"Usage: $0 {start|stop}"
        exit 1
esac
exit 0

之後將這個腳本放到 /etc/init.d/runmycommandatshutdown 中,然後 chkconfig on runmycommandatshutdown 使其可用,你的命令就會在關機時運行。


 在Slackware (sysvinit in BSD compatible mode)中更容易實現:

$ cat /etc/rc.d/rc.local_shutdown
#!/bin/sh
#
# /etc/rc.d/rc.local_shutdown: Local system shutdown script.
#
# Put any local shutdown commands in here.
my_command_at_shutdown
exit 0
$ sudo chmod +x /etc/rc.d/rc.local_shutdown

對於systemd

    這一切都很不錯,但是如果你運行的Linux版本使用Systemd而不是SysVinit呢?實際上在Systemd中更簡單。你所要做的就是將你的腳本放到由systemd-halt.service所管理的 /usr/lib/systemd/system-shutdown/ 目錄中去。當然,如果你需要在一個特定的情況下去管理依賴關係(例如你無法在沒網的情況下發推特),這時你可以寫一個系統服務組文件。例如:

[Unit]
Description=Run mycommand at shutdown
Requires=network.target
DefaultDependencies=no
Before=shutdown.target reboot.target
 
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=mycommand

[Install]
WantedBy=multi-user.target

補充:Shutdown Sequence Systemd

1.首先創建一個觸發服務(該服務需要是關機服務) 

# cat /lib/systemd/system/fakehalt.service

[Unit]
Description=Fake-Halt Service
After=fakevm.service
Requires=fakevm.service

[Service]
Type=simple
ExecStart=/usr/local/bin/fakehalt.sh #this will fail until fakevm succeeds
ExecReload=/usr/local/bin/fakehalt.sh

 2.然後創建一個系統允許的你想要在關機之前運行完成的命令文件

# cat /lib/systemd/system/fake.service
[Unit]
Description=Fake Service
Before=fakehalt.service

[Service]
Type=simple
ExecStart=/usr/local/bin/fake.sh

3.創建一個腳本來表示虛擬機關機(或任何你不能預見其持續時間的進程)

# cat /usr/local/bin/fake.sh
#!/bin/sh

test="1"
sleep 21
if [ X"$test" = "X1" ]; then
    echo "vm has shut down" > /tmp/fake.test
    exit 0
else 
    exit 1
fi

和一個用於關閉信號的腳本:

# cat /usr/local/bin/fakehalt.sh
#!/bin/sh

sleep 3
cat /tmp/vmfake.test > /tmp/haltfake.test

4.啓動

# systemctl start fakehalt

 有可能fakehalt找不到一個叫 /tmp/fake.test 的文件,然後一切都亂套了。實際情況是系統會保持 fakehalt 服務運行直到收到了 exit 0 信號。因此如果你在fakehalt開始後等21秒之後cat /tmp/fakehalt.test ,你會發現/tmp/fakehalt.test並不存在,因爲fakehalt已經成功執行了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章