Dane wyjściowe skryptu w tle lub skryptu rozruchowego


10

Mam krótki skrypt, który jest wykonywany przez demona systemu dla określonych zdarzeń. Wiem, że zdarzenie ma miejsce i skrypt działa, ale nie robi tego, co zamierzam. O dziwo dzieje się tak, gdy uruchamiam go ręcznie, więc jestem bardzo zdezorientowany.

Jak mogę dowiedzieć się, co się dzieje? Skrypt jest w zasadzie serią takich poleceń:

/bin/foo on 3
sudo bar a

Rozumiem, że ma to być samouczek na temat debugowania skryptów systemowych, ale jest też trochę U&L. Źle odczytałem tytuł i zasugerowałem „Rejestrowanie danych wyjściowych skryptu systemowego w celu debugowania”, by cel był bardziej przejrzysty. Również mój mózg zawiesza się, gdy czytam te foo barprzykłady, wolę coś, co wygląda bardziej realnie. Niechętnie edytuję dowolny post, więc zostawię to tobie, jeśli uważasz, że można go poprawić.
Milliways,

1
@Milliways Masz rację, „skrypt systemowy” i tak był trochę mylący, więc zmieniłem tytuł. Nie zgadzam się co do foobar - ludzie muszą nauczyć się rozpoznawać pospolite / kolokwializm tak samo, jak w każdej kulturze. Jest to nadal dobry chichot po połączeniu tych dwóch elementów.
złotowłosy

Odpowiedzi:


8

Po pierwsze, jeśli skrypt jest uruchamiany przez demona systemowego i ten demon działa z uprawnieniami administratora, nie trzeba go używać sudo. Obejmuje to init(i systemd), które obejmuje rc.local. Jeśli ten demon nie działa z uprawnieniami administratora, sudonie będzie działał, chyba że /etc/sudoersjest skonfigurowany tak, aby na to pozwalać (i bez hasła). Użytkownicy Raspbian mogą być tym zdezorientowani, ponieważ piużytkownik może domyślnie robić cokolwiek (a jeśli zajrzysz, /etc/sudoerszobaczysz, jak to się robi ).

Następnie możesz przechwycić dane wyjściowe z dowolnego bashskryptu lub dowolnego zestawu poleceń w skrypcie bash, wykonując je w podpowłoce: 1

(
    /bin/foo on 3
    sudo bar a
) &> /var/log/myTestLog.txt

()Wskazuje podpowłoce . Wszystkie dane wyjściowe z czegokolwiek w tym są przekierowywane do /var/log/myTestLog.txtpliku. Kilka uwag:

  • &>to bashizm , więc jeśli skrypt jest wykonywany za pomocą shebang w pierwszym wierszu, powinno być #!/bin/bash, nie tylko /bin/sh. „Bashizmy” działają tylko w bashpowłoce.

    Obejmuje to /etc/rc.local, które domyślnie używa /bin/sh(tj. Tak, możesz bezpiecznie zmienić to na /bin/bash).

  • /var/logwymaga uprawnień roota do pisania. Jeśli proces nie ma takiego, użyj lub utwórz katalog, który znasz. W razie wątpliwości, jeśli możesz to przetestować bez konieczności zamykania lub ponownego uruchamiania systemu, użyj polecenia /tmp, które można zapisać na całym świecie (tj. Przez kogokolwiek). Jednak /tmpnie utrzymują się po drugiej stronie butów. Jest to także mała partycja oparta na pamięci RAM, więc nie zapisuj na niej żadnych danych. To nie jest twoja karta SD [tak naprawdę jest w obecnych wersjach Raspbian, ale nie licz na to w praktyce] .

  • &>nadpisze wszystko w myTestLog.txt. Jeśli zamiast tego chcesz dołączyć do istniejącego dziennika, co może być dobrym pomysłem do celów debugowania, użyj &>>. Następnie możesz dodać polecenie na początku tej podpowłoki w następujący sposób:

    echo Starting $(date)

    Aby oddzielić informacje od każdego uruchomienia. Jeśli nie masz pewności, co to robi, spróbuj w wierszu polecenia.

Ten ostatni punkt jest dobrą ilustracją czegoś, co możesz zrobić w odniesieniu do poleceń, które niczego nie wypisują - ale większość z nich robi to, jeśli na przykład użyjesz słowa -v„gadatliwy”. Uwaga na niektóre polecenia -voznacza „informację o wersji wydruku”. Zajrzyj na stronę podręcznika, aby sprawdzić, czy polecenie to działa i jak to działa (niektóre polecenia również używają innego przełącznika niż -v).

Zgodnie z konwencją polecenia również zwracają wartość 0 po zakończeniu. Czasami nazywa się to „statusem wyjścia” i zwykle go nie widzisz, ale powłoka pokaże ci echo $?. Próbować

 ls /
 echo $?
 ls /nonexistantdir
 echo $?

Dostaniesz 0 i 2. Jeśli następnie przejrzysz stronę man lspod „Status wyjścia”, zobaczysz dość nieokreśloną, tajemniczą:

2      if serious trouble (e.g., cannot access command-line argument).

Co może, ale nie musi, być lepsze niż nic, ale proszę bardzo.

Przynajmniej oznacza to, że polecenie z jakiegoś powodu nie powiodło się. Status wyjścia umożliwia także wykonywanie takich czynności:

/bin/foo && sudo bar

W &&tym przypadku oznacza „jeśli pierwsze polecenie się powiedzie”, zakładając, że pierwsze polecenie stosuje konwencję zwracania 0 (dlatego zwykle tak się dzieje). Jeśli /bin/foonie działa, nie można go znaleźć itp., sudo barTo nigdy się nie wydarzy.

Użycie kombinacji rejestrowania komunikatów i wykonania warunkowego ( &&) powinno znacznie przybliżyć Cię do rozwiązania problemu lub przynajmniej uzyskać informacje, które mogą być przydatne dla innych osób w rozwiązaniu problemu. Bez tego, większość osób, które często mogą to zrobić, to zgadywanie.


1. Możesz wykonać to samo przekierowanie wyjścia dla całego skryptu od wewnątrz, używając:

exec &> /var/log/myTestLog.txt

Na górze (lub w dowolnym miejscu i będzie to dotyczyło wszystkiego później).


2

Jednym ważnym aspektem, który ludzie często zapominają, uruchamiając skrypty, ponieważ demony są środowisko powłoki, a $PATHw szczególności zmienne. W twoim przykładzie druga linia polega na $PATH: pełnej nazwie sudojest /usr/bin/sudo, a twoja powłoka użytkownika wie to tylko dlatego, że kazano jej szukać /usr/binpodczas szukania plików wykonywalnych. To samo dotyczy bar.

Biorąc pod uwagę, że sudonie jest to konieczne podczas uruchamiania skryptów jako demonów, druga linia powinna wyglądać następująco:

/path/to/bar a
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.