ดำเนินการคำสั่งก่อนปิดเครื่อง


52

ฉันต้องการรันคำสั่งง่าย ๆ ก่อนที่คอมพิวเตอร์จะปิดเครื่อง (การกำหนดเวลาไม่จำเป็น)

สำหรับการเริ่มต้นฉันสามารถใช้ / etc / rc.local; มีบางอย่างที่คล้ายกันสำหรับการปิดระบบ?

โปรดทราบว่าฉันยังต้องการใช้ปุ่มปิดการทำงานแบบรวมจากเมนู เช่นฉันไม่ต้องการใช้สคริปต์ที่กำหนดเองทุกครั้งที่ฉันปิดระบบผ่านเทอร์มินัล - มันต้องเป็นแบบอัตโนมัติ

คำตอบ:


42

Linux Mint ใช้ Ubuntu ดังนั้นฉันจึงคาดว่าระบบ runlevel น่าจะเหมือนกัน บน Ubuntu สคริปต์สำหรับ runlevels ที่แตกต่างกันจะถูกดำเนินการตามสถานะใน/etc/rc[0-6].dไดเรกทอรี Runlevel 0 สอดคล้องกับการปิดระบบและ 6 เพื่อรีบูต

โดยทั่วไปแล้วสคริปต์จะถูกเก็บไว้ใน/etc/init.dนั้นจากนั้น symlink จะถูกวางไว้ในไดเรกทอรีที่สอดคล้องกับ runlevels ที่คุณต้องการ

ดังนั้นในกรณีของคุณเขียนสคริปต์เก็บไว้ใน/etc/init.d/นั้นสร้าง symlink ในแต่ละ/etc/rc0.dและ/etc/rc6.d(ถ้าคุณต้องการทั้งคู่) ชี้ไปที่สคริปต์ของคุณ

สคริปต์ในแต่ละไดเรกทอรี runlevel จะถูกดำเนินการตามลำดับ asciibeticalดังนั้นหากคำสั่งภายใน runlevel สำคัญสำหรับคุณให้เลือกชื่อ symlink ของคุณตามลำดับ


ฉันเพิ่งดูไฟล์โครงกระดูกใน init.d (kubuntu แม่นยำ) และได้รับการข่มขู่เล็กน้อย ฉันต้องการเพิ่มคำสั่งสองสามคำที่สะท้อนถึงวันที่ปิดระบบเป็นไฟล์ภายใต้ / var / log ฉันสามารถทำสิ่งนั้นหรือต้องจัดการกับสิ่งอื่น ๆ ในแฟ้ม Skeleton หรือไม่?
Joe

2
@Joe - คุณไม่ต้องการสิ่งนั้นส่วนใหญ่เว้นแต่ว่าคุณต้องการให้สคริปต์ของคุณสามารถควบคุมได้เป็นบริการมาตรฐาน คุณจะไม่ทำลายอะไรเลยด้วยเสียงสะท้อนที่เรียบง่ายไปยังไฟล์บันทึกของคุณเองดังนั้นลองและดู
ire_and_curses

1
นี่คือตัวอย่างสคริปต์ init.d อย่างง่าย นอกจากนี้ยังง่ายและมีประสิทธิภาพมากขึ้นในการสร้างsudo update-rc.d /etc/init.d/myservice defaults
symlink

ฉันได้เขียน /etc/init.d/spark_shutdown.sh และสร้างลิงค์ใน /etc/rc0.d & /etc/rc6.d ตอนนี้ฉันจะยืนยันสคริปต์นี้ได้อย่างไรใน ubuntu aws ec2 อินสแตน
Ashish

10

ตอนนี้ตัวแปร Ubuntu และมิ้นท์ได้ย้ายไปที่ systemd ฉันพบวิธีแก้ไขปัญหาเก่าของฉันตามข้างต้นเป็นที่น่าพอใจน้อยลง ฉันค้นหาในเว็บเพื่อค้นหาวิธีใช้ systemd และลงเอยด้วยการรวมภูมิปัญญาของผู้อื่นและบันทึกไว้เป็นโพสต์บล็อกที่blogspot.com.auซึ่งมีบทช่วยสอนต่อไปนี้

ด้วย systemd คุณสามารถสร้างไฟล์หนึ่งหรือสองไฟล์เพื่อเรียกใช้สคริปต์ของคุณโดยใช้เทมเพลตด้านล่างและดำเนินการคำสั่งสองสามคำสั่ง ง่าย


เวอร์ชัน GUI

ขั้นแรกให้สร้างสคริปต์ที่คุณต้องการเรียกใช้เมื่อเริ่มต้นและ / หรือปิดระบบ ฉันสร้าง. scopening_atstart และ. scfullcopy_atend

จากนั้นตรวจสอบให้แน่ใจว่าไฟล์ทั้งสองนั้นสามารถเรียกใช้งานได้โดยคลิกขวาที่ไฟล์เลือกคุณสมบัติและตรวจสอบให้แน่ใจว่าภายใต้การอนุญาตคุณได้ทำเครื่องหมายที่อนุญาตให้เรียกใช้ไฟล์ปฏิบัติการเป็นโปรแกรม

สองไฟล์ที่ฉันสร้างเติมและบันทึกเนื้อหาของ ramdisk พวกเขายังสร้างไฟล์ในไดเรกทอรีบ้านของฉันเพื่อพิสูจน์ว่าบริการใช้งานได้ พวกเขาอยู่ในรูปแบบ:

#!/bin/sh
cp -pru /home/john/zRamdisk/subdirectory1/* /home/john/.wine/drive_c/subdirectory1/
rm /home/john/stop_time
date +%D' '%T > /home/john/stop_time

จากนั้นฉันก็เปิดตัวจัดการไฟล์ในฐานะรูทเปิด/etc/systemd/systemและสร้างไฟล์ startup.service และไฟล์ save-ramdisk.service เห็นได้ชัดว่าคุณสามารถเลือกชื่อของคุณเองและชื่อทั่วไปอาจรวมถึงไฟล์เริ่มต้นที่ชื่อ johns_start.service และไฟล์ปิดที่ชื่อ johns_shutdown.service อย่าเลือกชื่อบริการที่มีอยู่

[Unit]
Description=Startup Applications

[Service]
Type=oneshot
RemainAfterExit=false
ExecStart=/home/john/.scopening_atstart

[Install]
WantedBy=multi-user.target

และ

[Unit]
Description=Save Ramdisk to Wine drive C

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/home/john/.scfullcopy_atend

[Install]
WantedBy=multi-user.target

คุณสามารถใช้ไฟล์บริการเดียวกันโดยแทนที่เส้นทางแบบเต็มของสคริปต์ที่เรียกใช้งานได้ของฉัน

ในที่สุดสำหรับแต่ละคนดำเนินการคำสั่ง systemctl เปิดใช้งาน your_files_name (แต่ไม่มีบริการต่อท้าย) ดังนั้นอันแรกของฉันคือsystemctl enable startup

รีบูทคอมพิวเตอร์หนึ่งครั้งเพื่อเริ่มบริการ บริการเริ่มต้นจะถูกดำเนินการเมื่อใดก็ตามที่ systemd เข้าสู่เป้าหมายผู้ใช้หลายคนและบริการหยุดเมื่อออกจากเป้าหมายผู้ใช้หลายคน ไฟล์บริการทางเลือกที่มีเงื่อนไขการเปิดใช้งานที่แตกต่างกันจะอธิบายไว้ด้านล่าง


เวอร์ชันของ CLI (Command Line)

คำอธิบายนี้อนุมานว่าคุณทำงานจากโฮมไดเร็กตอรี่ของคุณแทนที่จะเป็น / home / john, ใช้ sudo ตามต้องการ, และตัวเลือกแก้ไขที่ฉันเขียนเป็นกลุ่มหรือ svim

สร้างเริ่มต้นและเปลือกปิดสคริปต์ด้วยบรรทัดแรกและทำให้พวกเขาปฏิบัติการใช้#!/bin/shchmod +x my_new_filename

สร้างสองไฟล์ดังกล่าวข้างต้นหรือในตัวอย่างนี้หนึ่งไฟล์เพื่อจัดการงานเริ่มต้นและปิด ผมจะรันสคริปต์ในไดเรกทอรีบ้านของฉัน แต่ @don_crissti แสดงให้เห็นทางเลือกบางอย่างที่กองแลกเปลี่ยน

vim /etc/systemd/system/start_and_stop.service

และคัดลอกในเนื้อหาไฟล์:

[Unit]
Description=Run Scripts at Start and Stop

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/home/john/.startup_commands  #your paths and filenames
ExecStop=/home/john/.shutdown_commands

[Install]
WantedBy=multi-user.target

จากนั้นเปิดใช้งานบริการด้วยคำสั่ง:

systemctl enable start_and_stop

และรีบูตระบบของคุณหลังจากที่บริการจะเปิดใช้งาน คำสั่งsystemctl is-enabled start_and_stopและsystemctl is-active start_and_stopสามารถใช้ในการตรวจสอบบริการใหม่ของคุณ


การเปลี่ยนเงื่อนไข Trigger สำหรับการปิดเครื่อง

ไฟล์ข้างต้นทั้งหมดใช้การเปิดหรือปิดของสภาพแวดล้อมที่มีผู้ใช้หลายคนเพื่อเริ่มการทำงานของสคริปต์ ไฟล์ด้านล่างใช้การเริ่มต้นกระบวนการปิดที่อาจเกิดขึ้นสี่ขั้นตอนเพื่อเริ่มต้นสคริปต์ การเพิ่มหรือลบเป้าหมายในบรรทัดก่อน + บรรทัด WantedBy จะช่วยให้คุณสร้างความแตกต่างที่ละเอียดยิ่งขึ้น:

ไฟล์นี้มีการเสนอในคำตอบที่สองของโพสต์นี้แต่ฉันไม่สามารถให้มันทำงานจนกว่าฉันจะเพิ่มส่วนการติดตั้ง

อีกครั้งแก้ไขสคริปต์ในและเปิดใช้งานได้โดยใช้/etc/systemd/service/ systemctl enable your_file_nameเมื่อฉันเปลี่ยนเป้าหมายฉันใช้systemclt disable file_nameคำสั่งแล้วเปิดใช้งานมันซึ่ง symlinked ไปยังไดเรกทอรีเป้าหมาย รีบูทและบริการจะทำงาน

[Unit]
Description=Do something required
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target
# This works because it is installed in the target and will be
#   executed before the target state is entered
# Also consider kexec.target

[Service]
Type=oneshot
ExecStart=/home/john/.my_script  #your path and filename

[Install]
WantedBy=halt.target reboot.target shutdown.target

7

คุณต้องใช้rc.shutdownสคริปต์การปิดระบบสำหรับเคอร์เนล Linux การอ้างอิงหน้า man ของ OpenBSD :

เมื่อระบบปิดการทำงานโดยใช้คำสั่ง reboot (8) หรือ halt (8) หรือเมื่อ init (8) ถูกส่งสัญญาณให้ทำเช่นนั้นหรือเมื่อมีการหยุดใช้แป้นพิมพ์ร้องขอ (หากสถาปัตยกรรมรองรับ) rc ( 8) ถูกเรียกด้วยอาร์กิวเมนต์ `` shutdown ''

ดังนั้นคุณเพียงเปิด rc.shutdown ของคุณและเพิ่มคำสั่งเชลล์ที่คุณต้องการใช้

UPDATE: เนื่องจาก Linux Mint ใช้ Ubuntu ซึ่งมีขั้นตอนการเริ่มต้น / ปิดที่แตกต่างกันนี่คือขั้นตอนที่เกี่ยวข้องกับคุณ:

/etc/rc*.d/เขียนสคริปต์เชลล์ที่คุณต้องการในการดำเนินการและคัดลอกไปยังไดเรกทอรีที่เกี่ยวข้องในของคุณ *สอดคล้องกับระดับการทำงานที่คุณต้องการให้สคริปต์ในการดำเนินการ
Ubuntu ตามหมายเลข Debian runlevel ดังนั้นคุณมี runlevel 0 เพื่อหยุดและ runlevel 6 สำหรับการรีบูต


1

สำหรับระบบ init ที่อ้างอิง SysV ที่ใช้ใน Debian Wheezy, Devuan และอนุพันธ์และอื่น ๆ คุณสามารถเลียนแบบพฤติกรรมของrc.shutdownอะนาล็อกได้rc.localดังนี้:

เพิ่มคำสั่งของคุณไปยังโครงกระดูกต่อไปนี้ของ/etc/rc.shutdown:

#!/bin/sh -e
#
# rc.shutdown
#

# <add your commands here, before exit 0>

exit 0

บันทึกสคริปต์และทำให้ไฟล์นั้นทำงานchmod a+x /etc/rc.shutdownได้

จากนั้นเพิ่มสคริปต์ใหม่/etc/init.d/rc.shutdownให้กับระบบของคุณด้วยเนื้อหาต่อไปนี้:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          rc.shutdown
# Required-Start:
# Required-Stop:
# X-Stop-After:      umountroot
# Default-Start:
# Default-Stop:      0 6
# Short-Description: Run /etc/rc.shutdown if it exist
### END INIT INFO


PATH=/sbin:/usr/sbin:/bin:/usr/bin

. /lib/init/vars.sh
. /lib/lsb/init-functions

do_stop() {
    if [ -x /etc/rc.shutdown ]; then
            [ "$VERBOSE" != no ] && log_begin_msg "Running local shutdown scripts (/etc/rc.shutdown)"
        /etc/rc.shutdown
        ES=$?
        [ "$VERBOSE" != no ] && log_end_msg $ES
        return $ES
    fi
}

case "$1" in
    start)
        # No-op
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop|status)
    do_stop
        exit 0
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

ทำให้สคริปต์นี้ทำงานได้

สร้าง symlink ใน /etc/rcuty06 เหมือนกัน:

cd /etc/rc0.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

และ

cd /etc/rc6.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown

ใช้insservเพื่อแก้ไข symlink และเพื่อสร้างไฟล์. depend.boot, .depend.start และ .depend.stop ที่จำเป็น:

insserv -v

คุณต้องเป็นรูทหรือใช้ sudo สำหรับคำสั่งทั้งหมดที่กล่าวถึงข้างต้น


วันนี้ฉันเสียเวลากับตัวนี้ไปซักหน่อยและไม่สามารถใช้งานกับ Ubuntu 16 ได้บางทีอาจเป็นฉันก็ได้ แต่วิธีแก้ปัญหาข้างต้นใช้ได้ผลทันที
Mike Q
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.