Làm cách nào để tiếp tục tập lệnh sau khi khởi động lại máy?


18

Tôi đang viết một kịch bản shell trong bash. Tại một số điểm trong tập lệnh, nó phát hiện ra rằng máy cần phải được khởi động lại trước khi tiếp tục. Vấn đề:

sudo reboot

Khi máy hoạt động trở lại, có nhiều công việc mà kịch bản này cần phải làm. Làm cách nào để định cấu hình thứ gì đó để tiếp tục thực hiện công việc trong tập lệnh này?

Tôi giả sử rằng có một số nơi tôi có thể viết một kịch bản shell để nó sẽ được thực thi trong lần khởi động lại tiếp theo. Đâu là một nơi như vậy? Tôi thấy rằng cron có một lệnh @reboot. Tôi cũng biết rằng các dịch vụ như Apache được khởi động khi khởi động. Một trong hai sẽ là cơ chế thích hợp? Nếu vậy, nó sẽ được kích hoạt như thế nào?

Kịch bản này chỉ cần chạy một lần, không phải mỗi lần khởi động lại. Vì vậy, nó sẽ phải đi đâu đó chỉ chạy trong lần khởi động lại tiếp theo hoặc có thể tự xóa sau khi chạy.

Câu hỏi này hỏi về cách lưu trạng thái ứng dụng của bạn sau khi khởi động lại. Kịch bản của tôi không có nhiều trạng thái, vì vậy tôi có thể quản lý nó. Tôi chỉ cần biết làm thế nào để kịch bản này kích hoạt một cái gì đó để chạy sau lần khởi động lại tiếp theo.

Phiên bản cụ thể của tôi là Ubuntu Linux 14.04. Tập lệnh gốc được quản trị viên hệ thống bắt đầu trên dòng lệnh (trái ngược với việc chạy từ cron).


Khởi động lại trong tập lệnh chỉ nên được sử dụng nếu bạn KHÔNG THỂ tránh nó. Ví dụ như cài đặt kernel mới. Tôi chắc rằng bạn có thể thực hiện công việc của mình mà không cần khởi động lại. Bạn có thể chỉ định lý do tại sao bạn cần khởi động lại?
hỗn loạn

1
Kịch bản lệnh này cài đặt một kernel mới (hay đúng hơn là gọi nâng cấp apt có thể làm như vậy). Nó cũng kiểm tra xem có thực sự cần khởi động lại hay không trước khi thực hiện khởi động lại.
Stephen Ostermiller

"Khởi động lại trong tập lệnh chỉ nên được sử dụng nếu bạn KHÔNG THỂ tránh nó." - @chaos Tại sao?
John Red

Câu trả lời:


16

Trên một hệ thống, điều duy nhất thực sự bền bỉ là một tệp. Đó là khá nhiều những gì bạn nên sử dụng. Đây là một giải pháp sử dụng tập lệnh init.d.

Hãy xem xét tập lệnh (đơn giản) /etc/init.d/myupdatesau:

#! /bin/sh

### BEGIN INIT INFO
# Provides:          myupdate
### END INIT INFO

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

case "$1" in
    start)
        /path/to/update/script
        ;;
    stop|restart|reload)
        ;;
esac

Nếu bạn kích hoạt nó update-rc.d myupdate defaults, starthành động sẽ được thực hiện khi khởi động. Bây giờ, khi tập lệnh cập nhật của bạn yêu cầu khởi động lại:

touch /var/run/rebooting-for-updates
sudo reboot

Với giải pháp này, bạn có thể chia tập lệnh cập nhật của mình thành hai phần:

before_reboot(){
    # Do stuff
}

after_reboot(){
    # Do stuff
}

if [ -f /var/run/rebooting-for-updates ]; then
    after_reboot
    rm /var/run/rebooting-for-updates
    update-rc.d myupdate remove
else
    before_reboot
    touch /var/run/rebooting-for-updates
    update-rc.d myupdate defaults
    sudo reboot
fi

Nó sẽ thực thi phần before_rebootmã, tạo một tệp /var/runvà khởi động lại. Khi khởi động, tập lệnh sẽ được gọi lại, nhưng vì tập tin tồn tại, after_rebootsẽ được gọi thay vì before_reboot.

Lưu ý rằng update-rc.dyêu cầu quyền root.

Không sử dụng tệp (từ nhận xét của Stephen Ostermiller ):

Nếu bạn quen thuộc với getoptstiện ích này, bạn có thể muốn sử dụng các tùy chọn thay vì các tệp. Trong tập lệnh init, gọi tập lệnh với:

/path/to/update/script -r

Và trong tập lệnh của bạn, hãy kiểm tra các tùy chọn thay vì các tệp. Gọi tập lệnh của bạn một lần mà không có tùy chọn và init.d sẽ gọi lại khi khởi động, lần này là với -r.

# Set AFTER_REBOOT according to options (-r).

if [ "x$AFTER_REBOOT" = "xyes" ]; then
    # After reboot
else
    # Before reboot
fi

Bạn sẽ tìm thấy thêm thông tin về xử lý tùy chọn ở đây (chỉ dành cho các tùy chọn ngắn) . Tôi cũng chỉnh sửa kịch bản của mình bằng các cuộc gọi để update-rc.dgiữ công việc này một lần (từ một bình luận khác).


2
Nó có thể đơn giản hơn để gọi /path/to/update/script --after-reboottừ /etc/init.d/myupdatehơn là dựa vào sự hiện diện của /var/run/rebooting-for-updates. Sau đó, nó sẽ có các đối số khác nhau khi chạy trực tiếp so với được gọi khi khởi động.
Stephen Ostermiller

Đẹp, không nghĩ về các lựa chọn. Cho phép tôi chỉnh sửa;)
John WH Smith

1
Ngoài ra, vì đây là công việc một lần, tôi có thể muốn thêm update-rc.d myupdate defaultsupdate-rc.d myupdate removevào chính kịch bản, cũng như viết và xóa /etc/init.d/myupdateđể nó không để các tập tin ngồi xung quanh.
Stephen Ostermiller

Tôi đã thực hiện điều này và nó hoạt động tốt. Điều khác duy nhất mà tôi sẽ thêm là hệ thống dựa trên Debian của tôi yêu cầu các mục bổ sung trong INIT INFOphần: wiki.debian.org/LSBInitScripts
Stephen Ostermiller

Tôi thực sự muốn giữ cho nó đơn giản;) Viết init.d thích hợp mất một ít thời gian, nhưng tôi rất vui vì bạn đã tìm hiểu thêm thông tin: các tập lệnh này có thể trở nên khá tiện dụng.
John WH Smith
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.