Wywołać polecenie / skrypt odłączony od terminala sterującego?

9

Badam zachowanie skryptu, który normalnie jest uruchamiany jako proces automatyczny (np. Cron, Jenkins). Skrypt może (ewentualnie) wywoływać polecenia, które zachowują się inaczej (szukając danych wejściowych od użytkownika), gdy są uruchamiane interaktywnie; na przykład patchzapyta, co zrobić z odwróconą łatką, i svnpoprosi o hasła, ale muszę zobaczyć, co się stanie, gdy zostaną uruchomione bez interakcji.

Przekonanie patch, że nie jest interaktywne, jest dość łatwe; Muszę tylko przekierować, stdoutaby nie być tty:

$ </dev/null > >(cat) /path/to/myscript --args

Jednak svnpołączy się z terminalem sterującym, jeśli istnieje; edycja skryptów do przejścia --non-interactivenie jest tak naprawdę opcją, ponieważ pochodzi ona z kilku poziomów i trudno byłoby mieć pewność, że znalazłem każde wywołanie.

Czy istnieje sposób na wywołanie skryptu / polecenia w sposób nieinteraktywny, bez kontrolującego terminala (więc /dev/ttyto nie istnieje)? Wolałbym, aby stdout / stderr nadal jechał do mojego terminalu.

(Znalazłem pytanie Uruchom skrypt w nieinteraktywnej powłoce? Ale odpowiedzi na to omawiają różnice między środowiskiem cron a środowiskiem użytkownika; już wyeliminowałem wszystkie różnice oprócz nieinteraktywności).

ecatmur
źródło

Odpowiedzi:

13

Musisz rozpocząć kolejną sesję nie podłączoną do terminala, więc na przykład:

$ setsid sh -c 'tty; ps -jp "$$"; echo test' < /dev/null > log 2>&1
$ cat log
not a tty
  PID  PGID   SID TTY          TIME CMD
19506 19506 19506 ?        00:00:00 sh
test

Zobacz także start-stop-daemonpolecenie znalezione w niektórych dystrybucjach Linuksa. Jest też daemonpolecenie.

Stéphane Chazelas
źródło
Co oznacza ten wynik? Wygląda bardzo tajemniczo.
anatoly techtonik
2
@anatolytechtonik ważnymi częściami są „not tty”, co jest wynikiem ttypotwierdzenia, że ​​nie ma terminalu na stdin, a „?” w kolumnie danych pswyjściowych TTY, która potwierdza, że ​​nie ma kontrolnego tty dla shprocesu (i wszystkiego, co działa pod nim).
mr. Spuratic
Aby uruchomić polecenie jak każde inne polecenie, użyj setsid -w. Przykład: setsid -w sh -c 'tty < /dev/tty'daje sh: 1: cannot open /dev/tty: No such device or address(uwaga: /dev/ttytwój kontrolny tty). Bez -wsetid uruchamia proces równolegle / w tle.
Tino
0

Prawdopodobnie będziesz chciał wykonać skrypt oczekiwania. Przykład z SVN:

/programming/609445/using-expect-to-login-into-svn

Bratchley
źródło
To nie działa; spodziewaj się uruchamia polecenia interaktywnie
ecatmur
Interaktywnie w jakim sensie? W tym sensie, że wymaga to wkładu użytkownika? Jeśli to masz na myśli, nie ma większego sensu oczekiwać w takim przypadku. Jednym z przykładów, dla których go używam, jest Solaris, w komendzie passwd nie ma opcji --stdin, więc mam skonfigurowaną cronjob, która wykonuje skrypt oczekiwania, który otacza passwd, aby podać losowe hasło do konta. Nie wymaga interakcji człowieka. Rozumiem, że jest to wymóg użytkownika. Mogłem jednak źle zrozumieć.
Bratchley,
W rzeczywistości im bardziej to czytam, tym bardziej zdaję sobie sprawę, że źle zrozumiałem, o co ci chodziło. Przeprosiny.
Bratchley,
0

Czasami musisz trzymać stdin otwarty (nie otrzymywać eof na stdin) (np. Oczekiwać). W takim przypadku zmień / dev / null na / dev / zero.

setsid sh -c 'make test' </dev/zero >log 2>&1
zrozumiałem
źródło