Đó là một câu hỏi cũ nhưng một điều cần làm rõ.
Trong khi câu trả lời bằng Carl Norum và dogbane là chính xác, giả định là thay đổi kịch bản của bạn để làm cho nó hoạt.
Những gì tôi muốn chỉ ra là bạn không cần phải thay đổi kịch bản:
#!/bin/bash
echo "This"
echo "is" >&2
echo "a" >&3
echo "test." >&4
Nó hoạt động nếu bạn gọi một cách khác:
./fdtest 3>&1 4>&1
có nghĩa để chuyển hướng các mô tả tập tin 3 và 4 đến 1 (là đầu ra tiêu chuẩn).
Điểm có ích là kịch bản là hoàn toàn tốt đẹp trong muốn viết thư cho mô tả khác hơn là chỉ 1 và 2 (stdout và stderr) nếu những mô tả được cung cấp bởi các quá trình cha mẹ.
dụ của bạn là thực sự khá thú vị bởi vì kịch bản này có thể viết đến 4 file khác nhau:
./fdtest >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt
Bây giờ bạn có đầu ra trong 4 tập tin riêng biệt:
$ for f in file*; do echo $f:; cat $f; done
file1.txt:
This
file2.txt:
is
file3.txt:
a
file4.txt:
test.
thú vị hơn là gì về nó là chương trình của bạn không cần phải có quyền ghi cho các tệp đó, vì nó không thực sự mở chúng.
Ví dụ, khi tôi chạy sudo -s
thay đổi người sử dụng gốc, tạo ra một thư mục như là người chủ, và cố gắng chạy lệnh sau khi sử dụng thường xuyên của tôi (RSP trong trường hợp của tôi) như thế này:
# su rsp -c '../fdtest >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt'
tôi nhận được một lỗi:
bash: file1.txt: Permission denied
Nhưng nếu tôi làm chuyển hướng bên ngoài của su
:
# su rsp -c '../fdtest' >file1.txt 2>file2.txt 3>file3.txt 4>file4.txt
(lưu ý sự khác biệt trong dấu nháy đơn) nó hoạt động và tôi nhận được:
# ls -alp
total 56
drwxr-xr-x 2 root root 4096 Jun 23 15:05 ./
drwxrwxr-x 3 rsp rsp 4096 Jun 23 15:01 ../
-rw-r--r-- 1 root root 5 Jun 23 15:05 file1.txt
-rw-r--r-- 1 root root 39 Jun 23 15:05 file2.txt
-rw-r--r-- 1 root root 2 Jun 23 15:05 file3.txt
-rw-r--r-- 1 root root 6 Jun 23 15:05 file4.txt
là 4 tác phẩm thuộc sở hữu của người chủ trong một thư mục sở hữu bởi root - mặc dù kịch bản không có quyền để tạo các tệp đó.
Ví dụ khác sẽ sử dụng chroot jail hoặc container và chạy chương trình bên trong nơi không có quyền truy cập vào các tệp đó ngay cả khi nó được chạy dưới dạng gốc và vẫn chuyển hướng các mô tả đó ra bên ngoài. cho toàn bộ hệ thống tệp hoặc bất kỳ thứ gì khác cho tập lệnh này.
Vấn đề là bạn đã khám phá ra một cơ chế rất thú vị và hữu ích. Bạn không phải mở tất cả các tệp bên trong tập lệnh như đã được đề xuất trong các câu trả lời khác. Đôi khi nó rất hữu ích để chuyển hướng chúng trong khi gọi script.
Nói tóm lại, đây:
echo "This"
thực sự là tương đương với:
echo "This" >&1
và chạy chương trình như:
./program >file.txt
là giống như:
./program 1>file.txt
Số 1 chỉ là số mặc định và nó là giá trị xuất chuẩn.
Nhưng ngay cả chương trình này:
#!/bin/bash
echo "This"
có thể sản xuất một lỗi "Bad mô tả". Làm sao? Khi chạy như:
./fdtest2 >&-
Kết quả sẽ là:
./fdtest2: line 2: echo: write error: Bad file descriptor
Thêm >&-
(mà cũng giống như 1>&-
) có nghĩa là kết thúc đầu ra tiêu chuẩn. Thêm 2>&-
sẽ có nghĩa là đóng stderr.
Bạn thậm chí có thể làm một điều phức tạp hơn.kịch bản ban đầu của bạn:
#!/bin/bash
echo "This"
echo "is" >&2
echo "a" >&3
echo "test." >&4
khi chạy với chỉ:
./fdtest
in:
This
is
./fdtest: line 4: 3: Bad file descriptor
./fdtest: line 5: 4: Bad file descriptor
Nhưng bạn có thể làm cho mô tả 3 và 4 làm việc, nhưng số 1 thất bại bằng cách chạy:
./fdtest 3>&1 4>&1 1>&-
Kết quả đầu ra:
./fdtest: line 2: echo: write error: Bad file descriptor
is
a
test.
Nếu bạn muốn mô tả cả 1 và 2 thất bại, chạy nó như thế này:
./fdtest 3>&1 4>&1 1>&- 2>&-
Bạn nhận:
a
test.
Tại sao? Không có gì thất bại? Nó đã làm nhưng không có tiêu chuẩn (tập tin mô tả số 2) bạn không thấy thông báo lỗi!
Tôi nghĩ rất hữu ích khi thử nghiệm theo cách này để có được cảm giác về cách các trình mô tả và chuyển hướng của chúng hoạt động.
Kịch bản của bạn là một ví dụ rất thú vị - và tôi cho rằng nó không bị hỏng chút nào, bạn chỉ sử dụng sai! :)
Đó là những gì tôi đang tìm kiếm! Vì vậy, tôi cần phải xác định một tập tin cho nó để sử dụng như một nơi lưu trữ tạm thời với lệnh exec, và sau đó đóng chúng khi tôi đã làm xong? Xin lỗi, tôi hơi mờ với lệnh exec, tôi không sử dụng nó nhiều. – Trcx
có, nhưng không phải tạm thời. Tệp sẽ tồn tại ngay cả sau khi chương trình của bạn hoàn tất. – dogbane
Điều đó có thể hoạt động độc đáo sau đó, tôi đang cố gắng cổng một số tập lệnh tương thích với crontab task scheduler, nhưng tôi gặp sự cố khi cron không cho phép đường ống của stdout trong tập lệnh. – Trcx