Dash odpowiednik samokierowania wyjścia skryptu

9

W Bash możesz przekierować wszystkie przyszłe standardowe wyjścia aktualnie uruchomionego skryptu. Na przykład za pomocą tego skryptu

exec > >(logger -t my-awesome-script)
echo 1
echo 2
echo 3

To skończy się w syslog:

Oct 26 01:03:16 mybox my-awesome-script[72754]: 1
Oct 26 01:03:16 mybox my-awesome-script[72754]: 2
Oct 26 01:03:16 mybox my-awesome-script[72754]: 3

Ale jest to specyficzne dla Bash i nagi exec z przekierowaniem nie działa w Dash.

Syntax error: redirection unexpected

Jak mogę sprawić, by działał w Dash, a może w obu powłokach?

Alex B.
źródło
Czy mógłbyś dokładnie wyjaśnić, czego potrzebujesz? Możesz przekierować za pomocą >w myślniku. Zdaję sobie sprawę, że wydajesz się prosić o coś innego, ale nie jestem w stanie powiedzieć, co to jest.
terdon
@terdon Rozszerzyłem wyjaśnienie.
Alex B,

Odpowiedzi:

6

Możesz po prostu zrobić:

{ commands
....
} | logger -t my_awesome_script

Możesz to zrobić za pomocą dowolnej powłoki.

Jeśli nie podoba ci się jego wygląd, być może skrypt powinien się zawinąć w funkcję.

#!/bin/sh
run() if     [ "$run" != "$$" ] || return
      then   sh -c 'run=$$ exec "$0" "$@"' "$0" "$@" |
             logger -t my-awesome-script
      fi
#script-body
run "$@" || do stuff
mikeserv
źródło
Ostatnia linia powinna być run ${1+"$@"} || do stufftaka, aby argumenty zostały zachowane.
Adam Katz
@AdamKatz - uwaga, execpt ${1+"$@"}nic "$@" nie robi. W każdym razie miał inne problemy.
mikeserv
"$@"przejdzie, ""gdy nie będzie żadnych argumentów, a ${1+"$@"}przekaże pusty ciąg, gdy nie będzie żadnych argumentów. Ma to ogromne znaczenie dla wielu programów, ponieważ parsują one ""jako pusty argument, podczas gdy (niecytowany) pusty ciąg nie byłby w ogóle interpretowany jako argument.
Adam Katz
@AdamKatz - bardzo stara powłoka Bourne'a (i nie spodziewałbym się znaleźć dashw takim systemie) , ale poza tym "$@"jest wyjątkowa, ponieważ przypadek zero-argumentów nie zastępuje argumentu zerowego dla powłok POSIX.
mikeserv
1
@AdamKatz - w rzeczywistości był to błąd nawet w starym bsh i nigdy nie powinien tak działać. Zostało to ostatecznie naprawione, ale nie wiem, czy na przykład powinno być konieczne w Solarisie 10. Youre rację $ * - robi wykazują takie same właściwości schludne z expabsion - Jego wyjątkowość onky odnosi się do zmiennej zawartości swojej ekspansji, choć zawsze będzie something.in moim zdaniem "${@+is especially cool $@}" . W końcu jednak nie różni się praktycznie niczym od starego ${1+”$@"}obejścia. Jeśli masz ksh93:"${1+quoted" not quoted "quoted again}"
mikeserv
5

Podstawianie procesów można łatwo symulować za pomocą nazwanych potoków.

mkfifo logger_input
logger -t my_awesome_script < logger_input &
exec > logger_input
echo 1
echo 2
echo 3

W rzeczywistości nazwane potoki są jednym z mechanizmów (drugi to /dev/fd), za pomocą których można zaimplementować podstawianie procesów bash.

chepner
źródło
Moim zdaniem najbardziej wszechstronny: przy pomocy tee mogę bezproblemowo przekierowywać do kilku strumieni. Tylko jedna rzecz: nie zapomnij usunąć utworzonego logger_input na końcu skryptu.
lauhub
2

Nie sądzę, żeby było to możliwe dash. O ile wiem z tej manstrony , nie obsługuje on podstawiania procesów.

Aby obejść ten problem , możesz wypróbować sugestię mikserv lub przekierować wszystko do pliku, a następnie po zakończeniu skryptu (prawdopodobnie jest to skrypt), dodaj zawartość tego pliku do programu rejestrującego:

$ exec > ~/foo/foo.txt
$ ls
$ echo something
$ cat foo/foo.txt | sudo logger -t my-awesome-script
terdon
źródło
W rzeczywistości podstawienie procesu - lub to, co inne powłoki nazywają podstawieniem procesu - jest łatwiejsze w dashinnych powłokach. Podstawienie procesu jest po prostu argumentem wskazującym na /dev/fd/[num]link do anonimowego potoku. dashrobi tutaj dokumenty z anonimowymi potokami, a nie generuje pliki tymczasowe, jak większość innych powłok. Tak cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\njest nie tylko funkcjonalny odpowiednik, można nawet dostać się do nazwy FD siebie. Jednak twoja uwaga jest słuszna, jeśli idzie się w drugą stronę - musisz otworzyć nowy FD execi proces, który go odczytuje.
mikeserv
2
@mikeserv: W jakim sensie cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\n„łatwiej” niż cat <(get output)?
ruakh
@mikeserv: Trzeba pamiętać o wielu zasadach; być może po prostu przyzwyczaiłeś się do nich, że nie zauważysz.
ruakh
@ruakh - cóż, jasne. < >przekierowania powłoki. Zasadniczo, jeśli wykonasz tylko dwa z nich, możesz także układać na kolejnych liniach. Ale tak, masz rację - lubię tutaj dokumenty. Mimo to, tyle rzeczy, które mogą wymagać zapamiętania, myślę, że łatwiej jest, gdy działają one uniwersalnie. Z drugiej strony wiele osób nie ma większego zastosowania dla innych pocisków, więc nie ma to dla nich znaczenia. Po prostu nie jestem wśród nich.
mikeserv
1
@mikeserv: Nie tylko heredoki, ale także /dev/fd/3(w tej precyzyjnej formie) i szczegóły tego, co dzieje się z białymi znakami. . . i jeśli o to chodzi, fakt, że całe to podejście działa w ogóle w Dash, gdy nie działa w innych powłokach, które mają wszystkie komponenty, oznacza, że ​​ogólne podejście jest specjalną zasadą do zapamiętania. (To przypomina mi o próbach stworzenia uproszczonego angielskiego z mniejszym słownictwem; wycinają słowa takie jak wytrwałość , ale ignorują równie trudne idiomy jak kontynuowanie .)
ruakh