Uruchamianie skryptu jako inny użytkownik

12

Stworzyłem skrypt w /etc/init.d/, który musi uruchamiać kilka innych skryptów od innych (nieuprzywilejowanych) użytkowników z ich katalogów domowych, tak jakby je uruchomili.

Uruchamiam te skrypty za pomocą: sudo -b -u <username> <script_of_a_particular_user>

I to działa. Ale dla każdego skryptu użytkownika, który kontynuuje działanie (na przykład jakiegoś watchdoga), widzę odpowiedni nadrzędny proces sudo, wciąż żywy i działający jako root. To tworzy bałagan na liście aktywnych procesów.

Moje pytanie brzmi: w jaki sposób mogę uruchomić (rozwidlić) inny skrypt z istniejącego skryptu bash jako inny użytkownik i pozostawić go jako osierocony (samodzielny) proces?

Bardziej szczegółowe wyjaśnienie: w
zasadzie staram się zapewnić innym użytkownikom komputera sposób uruchamiania rzeczy po uruchomieniu systemu lub zamknięciu systemu, uruchamiając pliki wykonywalne znajdujące się w odpowiednich podkatalogach znajdujących się w ich katalogu domowym, o nazwach .startUp i .shutDown. Ponieważ nie znalazłem żadnego innego sposobu, aby to zrobić, napisałem skrypt bash, który to robi i skonfigurowałem go jako skrypt usługi (na podstawie szkieletu) w /etc/init.d/, więc kiedy jest uruchomiony z argumentem start uruchamia wszystko z katalogów .startUp, a gdy jest uruchamiany z argumentem stop, uruchamia wszystko z katalogów .shutDown wszystkich użytkowników.

Alternatywnie jestem również zainteresowany, czy mógłbym użyć jakiegoś istniejącego rozwiązania do rozwiązania tego problemu.

AKTUALIZACJA
Rozejrzałem się trochę i znalazłem to pytanie: /unix/22478/detach-a-daemon-using-sudo

Zaakceptowano odpowiedź, aby użyć: sudo -u user sh -c "daemon & disown %1"działa dla mnie. Ale próbowałem też bez odrzucenia% 1 i jest tak samo. Więc to działa dla mnie tak, jak się spodziewałem:

sudo -u <username> bash -c "<script_of_a_particular_user> &"

Moje dodatkowe pytanie brzmi: dlaczego to działa bez sprzeciwu? czy mimo wszystko powinienem zrezygnować z odrzuconego połączenia z powodu jakiegoś potencjalnego szczególnego przypadku?

AKTUALIZACJA 2

Najwyraźniej to też działa:

su <username> -c "<script_of_a_particular_user> &"

Czy jest jakaś różnica między tym połączeniem a połączeniem sudo? Wiem, że to potencjalnie zupełnie inne pytanie. Ale ponieważ sam znajduję tutaj odpowiedzi, może ze względu na ten temat ktoś mógłby to tutaj wyjaśnić.

AKTUALIZACJA 3
Obie te metody za pomocą su lub sudo wytwarzają teraz nowy proces startpar (pojedynczy proces działający jako root) po uruchomieniu komputera. Widoczny na liście procesów jako:

startpar -f -- <name_of_my_init.d_script>

Dlaczego ten proces się pojawia? Oczywiście robię coś złego, ponieważ żaden inny skrypt init.d nie uruchamia tego procesu.

AKTUALIZACJA 4
Problem ze startpar został rozwiązany. Zacząłem od tego inne pytanie:
proces startpar pozostawał zawieszony podczas uruchamiania procesów z rc.local lub init.d

I kolejne pytanie do dalszego omówienia mechanizmów uruchamiania dla nieuprzywilejowanych użytkowników:
Zapewnienie normalnym użytkownikom (innym niż root) możliwości inicjalizacji i automatycznego uruchamiania

Ivan Kovacevic
źródło

Odpowiedzi:

18

Prawidłowa odpowiedź brzmiała: przekierowanie do standardowego wejścia, standardowego wyjścia i standardowego błędu wymaga / dev / null (lub jakiegoś prawdziwego pliku):

su someuser -c "nohup some_script.sh >/dev/null 2>&1 &"

su - zastąp tożsamość użytkownika parametrem someuser
-c - su, aby uruchomić określoną komendę
nohup - Uruchom komendę odporną na zawieszanie się. Aby zapobiec przypadkom, w których proces nadrzędny zakończy proces potomny. Dodano tutaj na wszelki wypadek. Ale w rzeczywistości nie ma żadnego efektu w moim konkretnym przypadku. To, czy jest potrzebne, zależy od środowiska (sprawdź shopt )
> / dev / null - Przekieruj standardowe wyjście na nic, po prostu je wyłączając.
2> i 1 - Przekieruj wyjście standardowego błędu (2) na wyjście standardowe (1), które jest przekierowywane na zero
i - odłącz od tła, przekieruje standardowe wejście również na / dev / null.

Zasadniczo dokładnie to robi narzędzie start-stop-daemon z Debiana dpkg. Dlatego wolę uruchamiać skrypty w ten sposób niż wprowadzać kolejne zewnętrzne wywołanie narzędzia w moim kodzie. start-stop-daemon jest przydatny w przypadkach, gdy masz w pełni uruchomione programy demona, które musisz uruchomić, i gdzie potrzebujesz dodatkowych funkcji, które zapewnia start-stop-daemon (na przykład sprawdzanie, czy określony proces już działa, aby nie działał uruchom go ponownie).

Warto również zauważyć, że możesz również zamknąć deskryptory plików swojego procesu zamiast przekierowywać je do / dev / null , na przykład:

su someuser -c "some_script.sh 0<&- 1>&- 2>&- &"

0 <& - Zamknij standardowe wejście (0)
1> & - Zamknij standardowe wyjście (1)
2> & - Zamknij standardowe wyjście błędów (2)

Kierunek znaków <> nie ma znaczenia, jeśli określono długi numer deskryptora pliku. To jest równie dobre:

su someuser -c "some_script.sh 0>&- 1>&- 2>&- &"

lub

su someuser -c "some_script.sh 0<&- 1<&- 2<&- &"

Jest jednak nieco krótszy sposób na napisanie tego, bez liczb dla stdin i stdout, gdzie kierunek ma znaczenie:

su someuser -c "some_script.sh <&- >&- 2>&- &" 

Gdy deskryptory plików zostaną zamknięte lub przekierowane do / dev / null ( start-stop-demon dokonuje przekierowania do / dev / null), proces można bezpiecznie uruchomić w tle jako demon. Jest to więc potrzebne, aby uniknąć problemów ( startpar ) z uruchamianiem skryptów podczas uruchamiania.

Wdrożyłem całe rozwiązanie od pierwszego pomysłu i umieściłem je w GitHub:
https://github.com/ivankovacevic/userspaceServices

Ivan Kovacevic
źródło
Ivan, czy lepiej jest używać su lub su -login? Czytam człowieka su, ale nie rozumiem tego konkretnego przypadku.
Massimo,
1
@Massimo, przepraszam za opóźnienie w mojej odpowiedzi! Sprawdź to pytanie: unix.stackexchange.com/questions/318572/... jest tam lepsza strona podręcznika wyjaśniająca to. Zasadniczo różnica polega na ustawianiu katalogu roboczego i zmiennych środowiskowych. Powiedziałbym, że dla takich przypadków użycia (robienie czegoś jako inny użytkownik) może być lepszym rozwiązaniem użycie -login
Ivan Kovacevic
3

Możesz użyć start-stop-daemon z init.d z --useropcją.

dmourati
źródło
Skomentowałem start-stop-demona w odpowiedzi pana Sharka, a także zaktualizowałem moją odpowiedź i moje pytanie (aktualizacja 4)
Ivan Kovacevic
2

Nie przetestowałem tego w pełni, ale myślę, że coś takiego:

/sbin/start-stop-daemon --background --start --exec /home/USER/.startUp --user USER --pidfile=/home/USER/.startUp.pid --make-pidfile

podczas uruchamiania, a następnie

/sbin/start-stop-daemon --stop --user USER --pidfile=/home/USER/.startUp.pid

podczas zamykania.

Obsługa skryptu .shutDown może być wykonywana przez coś podobnego do uruchamiania, ale nie możesz być pewien, że skrypty działają do końca, ponieważ i tak powinno nastąpić zamknięcie :-)

powinieneś załatwić sprawę, być może powinieneś wprowadzić jakieś przekierowanie wejściowe, ale wtedy będziesz musiał się martwić o wypełnienie plików dziennika.

Pan Shark
źródło
2
Zasadniczo to zadziałałoby! start-stop-daemon może pomyślnie uruchamiać procesy podczas rozruchu lub w inny sposób. Przetestowałem to. Pozbywa się również tego problemu z zawieszaniem procesu startpar. Jednak w początkowej rozmowie brakuje również --chuid USER. Bez niego uruchomiłby proces jako root. Plik pid powinien również zostać prawdopodobnie zapisany w katalogu / var / run /, ponieważ w przeciwnym razie generuje plik będący własnością root w katalogu osobistym użytkowników. Moim zdaniem jednak generyczne uruchomienie skryptu start-stop-demon wydaje się nieco przesadzone. Sprawdź moją odpowiedź, gdzie starałem się wyjaśnić, dlaczego.
Ivan Kovacevic
1

Próbowałeś używać su?

su -c /home/user/.startUp/executable - user

-c każe su wykonać polecenie, a ostatnim parametrem jest użytkownik, który wykona je jako.

Tero Kilkanen
źródło
tak, to działa, ale z pewnymi cytatami i dodanym znakiem handlowym. Uważam, że pisanie tego jest łatwiejsze: su <nazwa użytkownika> -c "/some/path/script.sh &" Zasadniczo używałem sudo, ponieważ wydawało się być czystsze, ale teraz wydaje się to lepsze niż użycie: sudo - u <nazwa użytkownika> bash -c "/some/path/script.sh &". Nie wiem, czy są jakieś różnice między tymi dwoma
Ivan Kovacevic