Wykonaj polecenie przed zamknięciem


52

Chcę wykonać proste polecenie tuż przed wyłączeniem komputera (czas nie jest konieczny).

Do uruchomienia mogę użyć /etc/rc.local; czy jest coś podobnego do zamknięcia?

Zauważ, że nadal chciałbym używać zintegrowanego przycisku zamykania z menu; tzn. nie chcę używać skryptu niestandardowego za każdym razem, gdy zamykam terminal - musi być automatyczny.

Odpowiedzi:


42

Linux Mint jest oparty na Ubuntu, więc przypuszczam, że system poziomu pracy jest prawdopodobnie taki sam. W systemie Ubuntu skrypty dla różnych poziomów uruchamiania są wykonywane zgodnie z ich obecnością w /etc/rc[0-6].dkatalogach. Poziom pracy 0 odpowiada wyłączeniu, a 6 - restartowi.

Zwykle sam skrypt jest przechowywany /etc/init.d, a następnie dowiązania symboliczne są umieszczane w katalogach odpowiadających wymaganym poziomom działania.

Więc w twoim przypadku napisz skrypt, zapisz go /etc/init.d/, a następnie utwórz w każdym z nich dowiązanie symboliczne /etc/rc0.di /etc/rc6.d(jeśli chcesz oba), wskazując na swój skrypt.

Skrypty w każdym katalogu poziomu pracy będą wykonywane w kolejności asciibetycznej , więc jeśli kolejność w poziomie pracy ma dla Ciebie znaczenie, wybierz odpowiednio nazwę swojego dowiązania symbolicznego.


Właśnie spojrzałem na plik szkieletu w init.d (precyzyjnie kubuntu) i trochę mnie zastraszyłem. Chcę tylko dodać kilka poleceń, które odzwierciedlają datę zamknięcia do pliku w / var / log. Czy mogę to po prostu zrobić, czy muszę poradzić sobie z niektórymi innymi sprawami w pliku szkieletu?
Joe

2
@Joe - Większość z tych rzeczy nie jest potrzebna, chyba że chcesz, aby skrypt mógł być kontrolowany jako standardowa usługa. Nic nie zepsujesz prostym echem do własnego pliku dziennika, więc spróbuj i przekonaj się.
ire_and_curses

1
Oto prosty przykładowy skrypt init.d. Ponadto łatwiej i solidniej jest tworzyć sudo update-rc.d /etc/init.d/myservice defaults
łącza

Napisałem /etc/init.d/spark_shutdown.sh i utworzyłem link w /etc/rc0.d & /etc/rc6.d teraz, jak mogę potwierdzić, że ten skrypt działał w instancji ubuntu aws ec2
Ashish Karpe

10

Teraz, gdy warianty Ubuntu i Mint zostały przeniesione do systemd, moje stare rozwiązania oparte na powyższym są mniej satysfakcjonujące. Szukałem w Internecie, aby dowiedzieć się, jak to zrobić za pomocą systemd, i ostatecznie połączyłem mądrość innych i udokumentowałem to jako post na blogu na blogspot.com.au zawierający następujący samouczek.

Za pomocą systemd możesz utworzyć jeden lub dwa pliki do wywoływania skryptów za pomocą poniższych szablonów i wykonać kilka poleceń. Prosty.


Wersja GUI

Najpierw utwórz skrypty, które chcesz uruchomić podczas uruchamiania i / lub zamykania systemu. Utworzyłem .scopening_atstart i .scfullcopy_atend.

Następnie upewnij się, że oba są wykonywalne, klikając prawym przyciskiem myszy plik, wybierając właściwości i upewniając się, że w ramach uprawnień zaznaczyłeś opcję Zezwalaj na uruchamianie pliku jako programu.

Dwa utworzone przeze mnie pliki zapełniają się i zapisują zawartość ramdysku. Tworzą również plik w moim katalogu domowym, aby udowodnić, że usługa działa. Były w formie:

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

Następnie otworzyłem menedżera plików jako root, otworzyłem /etc/systemd/systemi utworzyłem plik startup.service i plik save-ramdisk.service. Oczywiście możesz wybrać własne nazwy, a nazwy ogólne mogą zawierać plik startowy o nazwie johns_start.service i plik zamykania o nazwie johns_shutdown.service. Po prostu nie wybieraj istniejących nazw usług.

[Unit]
Description=Startup Applications

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

[Install]
WantedBy=multi-user.target

i

[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

Możesz użyć tych samych plików usługi, zastępując pełną ścieżkę skryptu wykonywalnego moim.

Na koniec dla każdego z nich wykonaj polecenie systemctl włącz nazwę_plików (ale bez usługi sufiksu). Więc mój pierwszy byłsystemctl enable startup

Uruchom ponownie komputer raz, aby uruchomić usługi. Usługa uruchamiania będzie wykonywana za każdym razem, gdy systemd wejdzie do celu dla wielu użytkowników, a usługa zatrzymania, gdy opuści cel dla wielu użytkowników. Alternatywne pliki usług z różnymi warunkami aktywacji zostaną opisane poniżej.


Wersja CLI (wiersza poleceń)

W tym opisie założono, że operujesz z katalogu domowego zamiast / home / john, w razie potrzeby korzystasz z sudo, a wybór edytora, w którym piszę vim lub svim.

Utwórz skrypty powłoki uruchamiania i zamykania w pierwszym wierszu #!/bin/shi włącz ich uruchamianie za pomocą chmod +x my_new_filename.

Utwórz dwa pliki jak wyżej lub w tym przykładzie jeden plik do obsługi zadań uruchamiania i zamykania. Wykonam skrypty w moim katalogu domowym, ale @don_crissti pokazuje kilka alternatyw w Stack Exchange .

vim /etc/systemd/system/start_and_stop.service

i skopiuj zawartość pliku:

[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

Następnie włącz usługę za pomocą polecenia:

systemctl enable start_and_stop

i uruchom ponownie system, po którym usługi będą aktywne. Polecenia systemctl is-enabled start_and_stopi systemctl is-active start_and_stopmogą być używane do monitorowania nowych usług.


Zmiana warunków wyzwalania dla zamknięcia

Przede wszystkim pliki używają otwartego lub zamkniętego środowiska wielu użytkowników, aby zainicjować uruchamianie skryptów. Poniższy plik wykorzystuje początek czterech potencjalnych procesów zamykania do inicjowania swoich skryptów. Dodanie lub usunięcie celów w linii Przed + linia WantedBy pozwoli ci na dokładniejsze rozróżnienie:

Ten plik został zaproponowany w drugiej odpowiedzi tego postu, ale nie mogłem go uruchomić, dopóki nie dodałem sekcji Instaluj.

Ponownie edytuj skrypt /etc/systemd/service/i włącz go, używając systemctl enable your_file_name. Kiedy zmieniłem cele, użyłem systemclt disable file_namepolecenia, a następnie ponownie je włączyłem, co dowiązało go do katalogów docelowych. Uruchom ponownie, a usługa będzie działać.

[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

Musisz użyć rc.shutdownskryptu zamykania jądra Linux. Cytując stronę podręcznika OpenBSD :

Kiedy system zostanie zamknięty za pomocą poleceń restartu (8) lub halt (8), lub gdy zostanie do tego zasygnalizowany init (8), lub gdy zostanie wydane polecenie zatrzymania na żądanie klawiatury (jeśli architektura go obsługuje), rc ( 8) jest wywoływany z argumentem `` zamknięcie ''.

Więc po prostu otwórz rc.shutdown i dodaj do niego wszelkie polecenia powłoki, które chcesz wykonać.

AKTUALIZACJA: Ponieważ Linux Mint jest oparty na Ubuntu, który ma inną procedurę uruchamiania / zamykania, oto procedura odpowiednia dla Ciebie:

Napisz skrypt powłoki, który chcesz wykonać, i skopiuj go do odpowiedniego katalogu w swoim /etc/rc*.d/. Do *odpowiada poziomu uruchomieniowego, w którym chcesz, aby wykonać skrypt.
Ubuntu podąża za numeracją poziomu uruchamiania Debiana, więc masz poziom działania 0 dla zatrzymania i poziom pracy 6 dla ponownego uruchomienia.


1

W przypadku systemów inicjujących opartych na zależności SysV używanych w Debian Wheezy, Devuan i jego pochodnych, a może także w innych, można naśladować zachowanie rc.shutdownanalogu rc.localw następujący sposób:

Dodaj swoje polecenia do następującego szkieletu /etc/rc.shutdown:

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

# <add your commands here, before exit 0>

exit 0

Zapisz skrypt i uczyń plik wykonywalnym za pomocą chmod a+x /etc/rc.shutdown.

Następnie dodaj nowy skrypt /etc/init.d/rc.shutdowndo systemu o następującej treści:

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

Również ten skrypt może być wykonywalny.

Utwórz dowiązania symboliczne w /etc/rc[06].d:

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

i

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

Służy insservdo poprawiania dowiązań symbolicznych i tworzenia niezbędnych plików .depend.boot, .depend.start i .depend.stop:

insserv -v

Musisz być rootem lub używać sudo dla wszystkich wyżej wymienionych poleceń.


Traciłem dzisiaj trochę ten czas i nie mogłem zmusić go do pracy z Ubuntu 16, być może to byłem ja, ale powyższe rozwiązanie zadziałało natychmiast.
Mike Q
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.