Zastępowanie komend / procesów POSIX
_log()( x=0
while [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ]
do continue; done &&
mkfifo -- "$TMPDIR/$$.$x" &&
printf %s\\n "$TMPDIR/$$.$x" || exit
exec >&- >/dev/null
{ rm -- "$TMPDIR/$$.$x"
logger --priority user."$1" --tag "${0##*/}"
} <"$TMPDIR/$$.$x" &
) <&- </dev/null
Powinieneś być w stanie używać takich jak:
exec >"$(_log notice)" 2>"$(_log error)"
Oto wersja, która korzysta z mktemp
polecenia:
_log()( p=
mkfifo "${p:=$(mktemp -u)}" &&
printf %s "$p" &&
exec <&- >&- <>/dev/null >&0 &&
{ rm "$p"
logger --priority user."$1" --tag "${0##*/}"
} <"$p" &
)
... co robi to samo, tyle że pozwala mktemp
wybrać nazwę pliku dla ciebie. Działa to, ponieważ podstawianie procesów w żadnym wypadku nie jest magiczne i działa w bardzo podobny sposób jak zastępowanie poleceń . Zamiast wymieniać ekspansję z wartością polecenia uruchomienia w nim jako podstawienie komenda robi, podstawienie proces zastępuje go z nazwą łącza systemu plików, gdzie można znaleźć wyjście.
Podczas gdy powłoka POSIX nie zapewnia bezpośredniego następstwa takiej rzeczy, emulowanie jej jest bardzo proste. Wszystko, co musisz zrobić, to utworzyć plik, wydrukować jego nazwę do standardu z podstawienia polecenia, a w tle tego samego polecenia uruchomić polecenie, które wyświetli się w tym pliku. Teraz możesz po prostu przekierować na wartość tego rozszerzenia - dokładnie tak, jak w przypadku zastępowania procesów. I tak powłoka POSIX zapewnia wszystkie narzędzia, których potrzebujesz, oczywiście - wystarczy, abyś użył ich w sposób, który ci odpowiada.
Obie powyższe wersje zapewniają, że niszczą łącze systemu plików do tworzonych / używanych przez siebie potoków, zanim jeszcze z nich skorzystają. Oznacza to, że po tym fakcie nie jest wymagane czyszczenie, a co ważniejsze, ich strumienie są dostępne tylko dla procesów, które je początkowo otwierają - a zatem ich łącza do systemu plików nie mogą być użyte jako sposób na szpiegowanie / przejęcie kontroli nad logowaniem. Pozostawienie linków fs w systemie plików stanowi potencjalną lukę w zabezpieczeniach.
Innym sposobem jest owinięcie go. Można to zrobić z poziomu skryptu.
x=${x##*[!0-9]*}
_log(){
logger --priority user."$1" --tag "${0##*/}"
} 2>/dev/null >&2
cd ../"$PPID.$x" 2>/dev/null &&
trap 'rm -rf -- "${TMPDIR:-/tmp}/$PPID.$x"' 0 ||
{ until cd -- "${TMPDIR:=/tmp}/$$.$x"
do mkdir -- "$TMPDIR/$$.$((x+=1))"
done &&
x=$x "$0" "$@" | _log notice
exit
} 2>&1 | _log error
To w zasadzie pozwoliłoby twojemu skryptowi wywoływać się, jeśli jeszcze tego nie zrobił, i uruchomić katalog roboczy w temp.