Linux
ExecStart 中的腳本退出時執行 ExecStop
我對 systemd 服務的行為有點困惑。我有上述系統服務。
[Unit] After=libvirtd.service [Service] Type=simple Environment=VM_XML=xxxxxxx ExecStartPre=/usr/bin/bash /usr/local/lib/common/createQcowImage.sh ${VM_XML} ExecStart=/usr/bin/bash /usr/local/lib/common/createVM.sh ${VM_XML} ExecStop=/usr/bin/bash /usr/local/lib/common/destroyVM.sh ${VM_XML} Restart=always [Install] WantedBy=multi-user.target
當這個單元在 createVM.sh 腳本中啟動時,它會創建一個 VM 並監控它的狀態。如果 VM 的 PID 不再存在,則腳本以返回碼 1 退出。我注意到,當發生這種情況時,ExecStop 被執行(我正在管理 /var/log/messages,當我手動銷毀 VM 時)使用 virsh destroy 我在從 ExecStop 執行的腳本中播下用於調試的迴聲,以列印在 /var/log/messages 中)。這是 systemd 的預設行為嗎?在單元退出時執行 ExecStop(我也嘗試使用程式碼 0 退出,這是相同的行為)。這不是我真正想做的,因為在我銷毀 VM 後,ExecStop 會嘗試銷毀導致 systemd 單元故障的同一 VM。有沒有辦法避免這種情況?
如果您想創建一個按預期執行的 systemd 服務配置,您需要充分了解所有選項的含義。
我建議您開始閱讀
man systemd.service
有關Type=
,ExecStart=
,ExecStop=
. 也許Type=exec
,或者Type=oneshot
更適合您的腳本?您描述的行為在我看來確實符合預期。
要處理您的 VM 已被其使用者停止的情況,您需要測試它是否仍在執行,如果沒有則避免破壞它。也不要忘記 ExecStop 必須等待機器停止,而不僅僅是要求它停止。
我附上了我用來啟動 VirtualBox VM 的使用者服務,也許你可以在那裡找到一些靈感。
[Unit] Description=Virtual Machine as a headless service. After=network.target virtualbox.target Before=runlevel2.target shutdown.target [Service] Type=simple Restart=no Environment=VMNAME=my-vbox-vm Environment=TIMEOUT=60 #ExecStartPre=VBoxManage snapshot $VMNAME take "before service start" ExecStart=VBoxHeadless --startvm $VMNAME # Sleep might be needed if there is some ExecStartPost later, to make sure that the VM was really powered up #ExecStartPost=sleep 1 # sometimes it happens that the machine is paused from some reason #ExecStartPost=bash -c "VBoxManage showvminfo $VMNAME | grep -E ^State:\\\\s+paused && VBoxManage controlvm $VMNAME resume || exit 0" # If the VM uses the VirtualBox hdd encryption, so a line like below is needed to unlock the drive #ExecStartPost=VBoxManage controlvm $VMNAME addencpassword $VMNAME "/home/user/VirtualBox VMs/my-vbxo-vm/my-vbox-vm.vmdk.pass" # The 'savestate' is the only reliable way to turn off the machine. # Optionally sending acpishutdown, can be considered, but better that needs to use the savestate as a fallback anyway, # because the acpishutdown can be from various reasons ignored by the VM or delayed significantly. # # Alternatives for ExecStop # - save state # (should be reliable but not really turning off the VM; # exit 0 necessary to handle the situation that VM was turned off already, # from inside) # ExecStop=bash -c "VBoxManage controlvm $VMNAME savestate || exit 0" # - stop vm using acpi, with active waiting # (not reliable - if acpi signal ignored by VM, or shutdown takes too long, # systemd will just kill it after some timeout, (normally 90s); # note that the active waiting is necessary, # otherwise systemd might kill the process before shutdown is finished) # ExecStop=bash -c "VBoxManage controlvm $VMNAME acpipowerbutton && while (VBoxManage list runningvms | grep $VMNAME); do sleep 1; done" # - stop vm using acpi or, after a timeout, with save state # (timeout let's say max 60s, to keep 30s for possible savestate; # exit 0 necessary in order not to have the service in error state when stopped already by acpi, or maybe even by user from inside of VM) ExecStop=bash -c "VBoxManage controlvm $VMNAME acpipowerbutton && (let timeout=$TIMEOUT; while VBoxManage list runningvms | grep --silent $VMNAME && test $timeout -gt 0; do sleep 1; let timeout=$timeout-1; done) && VBoxManage list runningvms | grep --silent $VMNAME && VBoxManage controlvm $VMNAME savestate || exit 0" [Install] WantedBy=default.target