Thay thế lệnh / quy trình 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
Bạn sẽ có thể sử dụng như thế:
exec >"$(_log notice)" 2>"$(_log error)"
Đây là phiên bản sử dụng mktemp
lệnh:
_log()( p=
mkfifo "${p:=$(mktemp -u)}" &&
printf %s "$p" &&
exec <&- >&- <>/dev/null >&0 &&
{ rm "$p"
logger --priority user."$1" --tag "${0##*/}"
} <"$p" &
)
... không giống nhau lắm, ngoại trừ việc nó cho phép mktemp
chọn tên tệp cho bạn. Điều này hoạt động bởi vì sự thay thế quá trình không có nghĩa là kỳ diệu và hoạt động theo cách rất giống với thay thế lệnh . Thay vì thay thế sự mở rộng bằng giá trị của lệnh chạy bên trong nó như thay thế lệnh , thay thế quá trình thay thế nó bằng tên của một liên kết hệ thống tập tin nơi có thể tìm thấy đầu ra.
Trong khi vỏ POSIX không cung cấp một hệ quả trực tiếp cho một điều như vậy, việc mô phỏng nó được thực hiện rất đơn giản. Tất cả những gì bạn cần làm là tạo một tệp, in tên của nó thành tiêu chuẩn thay thế lệnh và trong nền của cùng một lệnh chạy lệnh của bạn sẽ xuất ra tệp đó. Bây giờ bạn có thể chuyển hướng vào giá trị của bản mở rộng đó - chính xác như bạn làm với quy trình thay thế. Và vì vậy, vỏ POSIX cung cấp tất cả các công cụ bạn cần tất nhiên - tất cả những gì được yêu cầu là bạn đưa chúng vào sử dụng theo cách phù hợp với bạn.
Cả hai phiên bản trên đều đảm bảo rằng chúng phá hủy liên kết hệ thống tập tin đến các đường ống mà chúng tạo / sử dụng trước khi sử dụng chúng. Điều này có nghĩa là không có yêu cầu dọn dẹp sau thực tế, và quan trọng hơn, các luồng của chúng chỉ có sẵn cho các quy trình mở chúng ban đầu - và vì vậy các liên kết hệ thống tệp của chúng không thể được sử dụng như một phương tiện để theo dõi hoạt động đăng nhập của bạn. Để lại các liên kết fs của họ trong hệ thống tập tin là một lỗ hổng bảo mật tiềm năng.
Một cách khác là bọc nó. Nó có thể được thực hiện từ trong kịch bản.
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
Điều đó về cơ bản sẽ cho phép tập lệnh của bạn tự gọi nếu nó chưa có và giúp bạn có một thư mục công việc trong temp để khởi động.