Napisałem skrypt powłoki do testowania interfejsu API, który kopiuje pliki i po każdym powtarza jego postęp.
Pomiędzy każdą kopią jest dwusekundowy sen, dlatego chciałbym dodać możliwość naciśnięcia dowolnego klawisza, aby wstrzymać skrypt i umożliwić głębsze testowanie. Następnie naciśnij dowolny klawisz, aby wznowić.
Jak mogę to dodać w jak najmniejszej liczbie wierszy?
shell-script
blarg
źródło
źródło
sleep 10; notify-send hello
i naciśnij klawisze CTRL + Z, aby zatrzymać, wykonaj polecenienotify-send hello
. jeśli wykonywane jest drugie polecenie, dlaczego pierwszy proces zostaje zatrzymany? potem, jeśli typfg
i nie mogę zobaczyć, co się dzieje, co jest oczywiste, ponieważ drugie polecenie jest już wykonanecmd; cmd; cmd;
jest jak pisaniecmd <newline> cmd <newline> ...
. Alternatywnie do skryptu, który możesz napisać( cmd; cmd; cmd; )
, działałby on jak skrypt, ponieważ wygenerowano podpowłokę(
sleep 10
. kiedy naciskam CTRL + Z po 3 sekundach i wznawiam po kilku sekundach i zauważyłem, że polecenie uśpienia umarło w czasie krótszym niż 7 sekund. co jest przeciwieństwem tego, co powiedziałeś, ponieważ polecenie nevers zostaje zatrzymane, po prostu działa w tle.strace
dsleep
polecenia i okazało się, że wywołanie system wykorzystywany jestnanosleep()
. Wydaje się, że jest to określone zachowanienanosleep
wywołania systemowego.restart_syscall()
ponownie uruchamia przerwane wywołanie systemowe z argumentem czasu, który jest odpowiednio dostosowywany, aby uwzględnić czas, który już upłynął (w tym czas, w którym proces został zatrzymany przez sygnał). Przeczytaj tę stronę: man7.org/linux/man-pages/man2/restart_syscall.2.htmlfg %1
lub w tle (ex:)bg %1
. (jeśli zadania podają tylko 1 liczbę, tzn. tylko 1 zawieszony proces, jak pokazano w przykładzie chaosu: tylko[1]+ stopped sleep 10
, możesz pominąć%n
część. jeśli jest kilka procesów w tle (uruchomionych lub zatrzymanych), musisz wyznaczyć ten, który chcesz z:%n
(np.fg %2
aby wznowić% 2 na pierwszym planie))Jeśli chcesz po prostu zatrzymać skrypt, pozostając w nim, możesz użyć odczytu zamiast snu.
Możesz użyć
read -t
ustawić limit czasu odczyturead -n
dla odczytu jednego znaku (w rzeczywistości wystarczy nacisnąć dowolny klawisz), aby kontynuować skryptPonieważ nie podałeś żadnego kodu, poniżej znajduje się przykład jego użycia.
Naciśnięcie q
read -n1
uniemożliwia kontynuowanie skryptu do momentu naciśnięcia klawisza.Po naciśnięciu klawisza sprawdzanie jest resetowane, a skrypt kontynuuje normalną pętlę.
Możesz także dodać
stty -echo
na początku sekcji istty echo
na końcu, aby zapobiec nieporządkowi pisania na ekranieźródło
Dzięki
dd
niemu możesz niezawodnie odczytać pojedynczy bajt z pliku. Za pomocąstty
można ustawićmin
liczbę bajtów, aby zakwalifikować terminal do odczytu i dotime
dziesiątych części sekundy. Po połączeniu tych dwóch elementów możesz to zrobićsleep
całkowicie, myślę, i pozwól, aby limit czasu odczytu terminala wykonał pracę za Ciebie:To jest mała przykładowa
while
pętla, którą przygotowałem, abyś mógł ją wypróbować. Co dwie sekundydd
kończy się próba odczytaniastdin
- przekierowanie z/dev/tty
- iwhile
pętli pętli. To lubdd
nie kończy się, ponieważ naciskasz klawisz - w takim przypadku wywoływana jest interaktywna powłoka.Oto przebieg testowy - liczby wydrukowane na początku każdego wiersza są wartością zmiennej powłoki
$SECONDS
:źródło
stty sane
po zmianie ustawień stty, mogę się mylić, ale nie wygląda na to, że nigdzie je zresetowałeś?s=$(stty -g </dev/tty)
. Natychmiast po wywołaniudd
przywracam go za pomocąstty "$s"
. Stan terminalu nie dba o podpowłoki, więc te ustawienia zostają zachowane niezależnie od powłoki nadrzędnej.stty sane
niekoniecznie jest to, co chcesz zrobić - lepiej przywrócić stan do stanu, w którym go znalazłeś, niż założyć, że stan byłsane
w tym momencie. Gdybym tego nie przywrócił, teecho
byłyby wszędzie. Zrozumienie tego jest częściowo powodem, dla którego przyjechałem tak późno - Twoja odpowiedź nie pojawiła się tutaj, kiedy zacząłem testować.