Dostęp do kodu wyjścia poza su -m $ USER -c „<cmd>”

8

Poniższe polecenie drukuje „0” lub „1” poprawnie w zależności od niepowodzenia, czy nie, ponieważ wstawiłem $? wewnątrz polecenia „su”.

sudo su -m $USER -c "./shutdown.sh &> /dev/null; echo \$?"

Jeśli jednak to zrobię:

sudo su -m $USER -c "$BASE/bin/shutdown.sh &> /dev/null"; echo $?

zawsze wypisze „0”, ponieważ faktyczne „su” zawsze się powiedzie, nawet jeśli część polecenia nie powiedzie się.

Masz pomysł, jak mogę pobrać kod wyjścia podpowłoki?

Nacięcie
źródło

Odpowiedzi:

7

Właśnie naprawiłem prawie dokładnie tę samą sytuację. Mam nadzieję, że nadal ci to pomoże, jeśli nie, być może inni. Zacząłem od su, nie sudo, ale ponieważ sudo ma na celu zawinięcie jednej innej komendy, to naprawdę powinno przekazywać kod wyjścia su. Jeśli nie, możesz zastosować poniższą poprawkę również na poziomie sudo.

Jak zauważyłeś, głównym problemem jest to, że su z powodzeniem wykonuje swoje polecenie. Domyślnym działaniem jest następnie zgłoszenie, że zakończyło się ono bez żadnych problemów, a więc zwraca kod wyjścia 0. Nie „wie”, że kod wyjścia inny niż 0 z polecenia był nieoczekiwany lub że powinien coś z tym zrobić. Zatem rozwiązaniem jest po prostu zmusić su do zwrócenia kodu wyjścia z ostatniego polecenia. Zrobiło to dla mnie

su <user_x> -c '<bunch_of_commands>; exit $?'

W przypadku, gdy sudo nie gra dobrze, całe polecenie powinno być mniej więcej tak (sprawdziłbym to dla ciebie, ale nie mam zainstalowanego sudo)

sudo 'su <user_x> -c \'<bunch_of_commands>; exit $?\'; exit$?'

Uważaj na zagnieżdżanie cytatów i upewnij się, że $? nie zostanie rozwinięty, więc nie ma podwójnych cudzysłowów.

Captain Coder
źródło
2

Wypisz wartość zwracaną w poleceniu i uzyskaj do niej dostęp na zewnątrz, przypisując całe polecenie do zmiennej (używając podpowłoki).

RETVAL=$(sudo su -m $USER -c "./shutdown.sh &> /dev/null; echo \$?")
echo $RETVAL
Aaron Copley
źródło
0

Zawsze możesz użyć pliku tmp:

$ sudo su -m $USER -c "$BASE/bin/shutdown.sh &> /dev/null; echo \$? > /tmp/exit_code"; cat /tmp/exit_code
terdon
źródło
Tak, właśnie to robię teraz, ale miałem nadzieję, że nie będę polegać na pliku tmp.
Nick
0

Działa to w powłokach Zsh / Bash / Bourne:

$ sudo su -m $USER -c "$BASE/bin/shutdown.sh &> /dev/null"
$ echo $?

Nie jestem pewien, dlaczego kod powrotu nie jest dostępny, gdy o to poprosisz w jednej linijce, ale jest dostępny, gdy używasz więcej niż jednej linii do zrobienia tego samego.

zero2cx
źródło
To właściwie nie jest poprawne. To zawsze zwróci zero, ponieważ „su -m $ USER -c <cmd>” zawsze się powiedzie, nawet jeśli samo polecenie w nim nie działa.
Nick
1
@Nick - Działa tutaj. Jaka jest twoja produkcja? Spróbuj, sudo su -m zero2cx -c "/bin/false &> /dev/null"ale z nazwą użytkownika systemu. $?powinno być „1”.
zero2cx 21.09.12
Tak, moja własna nazwa użytkownika zwraca „1” zgodnie z oczekiwaniami. Ale próbuję użyć tego do uruchomienia aplikacji za pośrednictwem własnego użytkownika, a nie roota ani żadnego innego użytkownika.
Nick
@Nick - Powinien działać z $ USER=appusernamesetem, jak chcesz. Nie używaj prawdziwej nazwy użytkownika, odczytaj użytek zgodnie z przeznaczeniem appusername. To powinno działać, to działa dla mnie.
zero2cx