Thực hiện một lệnh trước khi tắt máy


52

Tôi muốn thực thi một lệnh đơn giản ngay trước khi máy tính tắt (thời gian không cần thiết).

Để khởi động, tôi có thể sử dụng /etc/rc.local; Có cái gì đó tương tự để tắt máy?

Lưu ý rằng tôi vẫn muốn sử dụng nút tắt tích hợp từ menu; tức là tôi không muốn sử dụng tập lệnh tùy chỉnh mỗi lần tắt máy qua thiết bị đầu cuối - nó cần phải tự động.

Câu trả lời:


42

Linux Mint dựa trên Ubuntu, vì vậy tôi đoán hệ thống runlevel có lẽ giống nhau. Trên Ubuntu, các tập lệnh cho các đường chạy khác nhau được thực thi theo sự hiện diện của chúng trong các /etc/rc[0-6].dthư mục. Runlevel 0 tương ứng với tắt máy và 6 để khởi động lại.

Thông thường, chính tập lệnh được lưu trữ /etc/init.dvà sau đó các liên kết tượng trưng được đặt trong các thư mục tương ứng với các đường dẫn bạn yêu cầu.

Vì vậy, trong trường hợp của bạn, hãy viết tập lệnh của bạn, lưu nó vào /etc/init.d/, sau đó tạo một liên kết tượng trưng trong mỗi /etc/rc0.d/etc/rc6.d(nếu bạn muốn cả hai) trỏ đến tập lệnh của bạn.

Các tập lệnh trong mỗi thư mục runlevel sẽ được thực thi theo thứ tự chính xác , vì vậy nếu thứ tự trong runlevel quan trọng với bạn, hãy chọn tên của liên kết tượng trưng cho phù hợp.


Tôi vừa xem tập tin bộ xương trong init.d (chính xác là kubfox) và có một chút sợ hãi. Tôi chỉ muốn thêm một vài lệnh lặp lại ngày tắt máy vào một tệp trong / var / log. Tôi chỉ có thể làm điều đó hay tôi phải đối phó với một số điều khác trong tập tin bộ xương?
Joe

2
@Joe - Bạn không cần hầu hết những thứ đó trừ khi bạn muốn tập lệnh của mình được kiểm soát như một dịch vụ tiêu chuẩn. Bạn sẽ không phá vỡ bất cứ điều gì với một tiếng vang đơn giản vào tệp nhật ký của riêng bạn, vì vậy hãy thử nó và xem.
ire_and_curses

1
Đây là một tập lệnh init.d mẫu đơn giản. Ngoài ra, việc tạo các liên kết tượng trưng bằng cách sử dụng dễ dàng và mạnh mẽ hơnsudo update-rc.d /etc/init.d/myservice defaults
RolfBly

Tôi đã viết /etc/init.d/spark_shutdown.sh và tạo liên kết của trong /etc/rc0.d & /etc/rc6.d bây giờ làm cách nào để xác nhận tập lệnh này chạy trong ví dụ ub Ubuntu aws ec2
Ashish Karpe

10

Bây giờ các biến thể Ubuntu và Mint đã chuyển sang systemd, tôi thấy các giải pháp cũ của tôi dựa trên những điều trên là không thỏa đáng. Tôi đã tìm kiếm trên web để tìm hiểu làm thế nào để làm điều đó với systemd và cuối cùng kết hợp sự khôn ngoan của người khác và ghi lại nó như một bài đăng trên blog tại blogspot.com.au có chứa hướng dẫn sau đây.

Với systemd, bạn tạo một hoặc hai tệp để gọi các tập lệnh của mình bằng các mẫu bên dưới và thực thi một vài lệnh. Đơn giản.


Phiên bản GUI

Đầu tiên tạo tập lệnh bạn muốn chạy khi khởi động và / hoặc tắt máy. Tôi đã tạo .scopening_atstart và .scfullcopy_atend.

Sau đó, đảm bảo rằng cả hai đều có thể thực thi được bằng cách nhấp chuột phải vào tệp, chọn thuộc tính và đảm bảo rằng, dưới quyền, bạn đã đánh dấu Cho phép thực thi tệp dưới dạng chương trình.

Hai tệp tôi đã tạo cư trú và lưu nội dung của một đĩa RAM. Họ cũng tạo một tập tin trong thư mục nhà của tôi để chứng minh rằng dịch vụ đang hoạt động. Chúng có dạng:

#!/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

Sau đó, tôi đã mở trình quản lý tệp của mình dưới dạng root, mở /etc/systemd/systemvà tạo tệp startup.service và tệp save-ramdisk.service. Rõ ràng bạn có thể chọn tên riêng của mình và tên chung có thể bao gồm một tệp khởi động được gọi là johns_start.service và một tệp tắt máy có tên là johns_shutdown.service. Chỉ không chọn tên dịch vụ hiện có.

[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

Bạn có thể sử dụng cùng các tệp dịch vụ, thay thế đường dẫn đầy đủ của tập lệnh thực thi của bạn cho tôi.

Cuối cùng, với mỗi người thực thi lệnh systemctl, hãy kích hoạt your_files_name (nhưng không có dịch vụ hậu tố). Vì vậy, cái đầu tiên của tôi làsystemctl enable startup

Khởi động lại máy tính một lần để bắt đầu dịch vụ. Dịch vụ khởi động sẽ được thực thi bất cứ khi nào systemd đi vào mục tiêu nhiều người dùng và dịch vụ dừng khi thoát khỏi mục tiêu nhiều người dùng. Các tệp dịch vụ thay thế với các điều kiện kích hoạt khác nhau sẽ được mô tả bên dưới.


Phiên bản CLI (Dòng lệnh)

Mô tả này giả định rằng bạn hoạt động từ thư mục chính của bạn chứ không phải / home / john, sử dụng sudo khi cần và lựa chọn biên tập viên của bạn nơi tôi viết vim hoặc svim.

Tạo các kịch bản shell khởi động và tắt với dòng đầu tiên #!/bin/shvà làm cho chúng có thể thực thi được bằng cách sử dụng chmod +x my_new_filename.

Tạo hai tệp như trên hoặc trong ví dụ này, một tệp để xử lý các tác vụ khởi động và tắt máy. Tôi sẽ thực thi các tập lệnh trong thư mục nhà của mình nhưng @don_crissti hiển thị một số lựa chọn thay thế tại Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

và sao chép trong nội dung tập tin:

[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

Sau đó kích hoạt Dịch vụ bằng lệnh:

systemctl enable start_and_stop

và khởi động lại hệ thống của bạn sau đó các dịch vụ sẽ hoạt động. Các lệnh systemctl is-enabled start_and_stopsystemctl is-active start_and_stopcó thể được sử dụng trong việc giám sát các dịch vụ mới của bạn.


Thay đổi điều kiện kích hoạt để tắt máy

Tất cả các tệp trên đều sử dụng mở hoặc đóng môi trường nhiều người dùng để bắt đầu chạy các tập lệnh. Các tập tin dưới đây sử dụng bắt đầu của bốn quá trình tắt máy tiềm năng để bắt đầu các tập lệnh của nó. Thêm hoặc xóa các mục tiêu trên dòng Before + dòng WantedBy sẽ cho phép bạn tạo ra sự khác biệt tốt hơn:

Tập tin này đã được đề xuất trong câu trả lời thứ hai của bài đăng này nhưng tôi không thể chạy nó cho đến khi tôi thêm phần Cài đặt.

Một lần nữa, chỉnh sửa tập lệnh trong /etc/systemd/service/và kích hoạt nó bằng cách sử dụng systemctl enable your_file_name. Khi tôi thay đổi các mục tiêu, tôi đã sử dụng systemclt disable file_namelệnh và sau đó kích hoạt lại nó để liên kết nó với các thư mục đích. Khởi động lại và dịch vụ sẽ được vận hành.

[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

Bạn cần sử dụng rc.shutdowntập lệnh tắt cho Linux Kernel. Trích dẫn trang người dùng OpenBSD :

Khi hệ thống bị tắt bằng cách sử dụng các lệnh khởi động lại (8) hoặc tạm dừng (8) hoặc khi init (8) được báo hiệu để làm như vậy hoặc khi lệnh dừng yêu cầu bàn phím được phát ra (nếu kiến ​​trúc hỗ trợ), RC ( 8) được gọi với đối số `` shutdown ''.

Vì vậy, bạn chỉ cần mở RC.shutdown của bạn và thêm bất kỳ lệnh shell nào bạn muốn thực hiện với nó.

CẬP NHẬT: Vì Linux Mint dựa trên Ubuntu, có quy trình khởi động / tắt máy khác nhau, đây là quy trình phù hợp với bạn:

Viết kịch bản shell mà bạn muốn thực thi và sao chép nó vào thư mục có liên quan trong của bạn /etc/rc*.d/. Các *tương ứng với runlevel mà tại đó bạn muốn tập lệnh thực thi.
Ubuntu tuân theo cách đánh số runlevel của Debian, vì vậy bạn có runlevel 0 để tạm dừng và runlevel 6 để khởi động lại.


1

Đối với các hệ thống init dựa trên SysV được sử dụng trong Debian Wheezy, Devuan và các dẫn xuất của nó và có thể là các hệ thống khác, bạn có thể bắt chước hành vi của rc.shutdowntương tự rc.localnhư sau:

Thêm các lệnh của bạn vào bộ xương sau /etc/rc.shutdown:

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

# <add your commands here, before exit 0>

exit 0

Lưu tập lệnh và làm cho tập tin thực thi với chmod a+x /etc/rc.shutdown.

Sau đó, thêm một tập lệnh mới /etc/init.d/rc.shutdownvào hệ thống của bạn với nội dung sau:

#! /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

Cũng làm cho kịch bản này thực thi.

Tạo các liên kết tượng trưng trong /etc/rc[06[.d:

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

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

Sử dụng insservđể sửa các liên kết tượng trưng và tạo các tệp .depend.boot, .depend.start và .depend.stop cần thiết:

insserv -v

Bạn cần phải root hoặc sử dụng sudo cho tất cả các lệnh được đề cập ở trên.


Tôi đã lãng phí thời gian của mình với cái này một chút hôm nay và không thể làm cho nó hoạt động được với Ubuntu 16, có lẽ đó là tôi nhưng giải pháp ở trên đã hoạt động ngay lập tức.
Mike Q
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.