Sự khác biệt giữa các lệnh là gì
$ env FOO=bar baz
và
$ FOO=bar baz
Có ảnh hưởng gì không env
?
Sự khác biệt giữa các lệnh là gì
$ env FOO=bar baz
và
$ FOO=bar baz
Có ảnh hưởng gì không env
?
Câu trả lời:
Chúng tương đương về chức năng.
Sự khác biệt chính là env FOO=bar baz
liên quan đến việc gọi một quá trình trung gian giữa vỏ và baz
, trong đó như với FOO=bar baz
vỏ trực tiếp gọi baz
.
Vì vậy, trong vấn đề đó, FOO=bar baz
được ưa thích.
Các tình huống duy nhất tôi thấy mình sử dụng env FOO=bar
là khi tôi phải truyền một lệnh cho một lệnh khác.
Như một ví dụ cụ thể, giả sử tôi có một tập lệnh bao bọc thực hiện một số sửa đổi của môi trường và sau đó gọi exec
lệnh được truyền cho nó, chẳng hạn như:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Nếu bạn thực hiện nó như là myscript FOO=bar baz
, exec
sẽ ném một lỗi exec FOO=bar baz
là không hợp lệ.
Thay vào đó, bạn gọi nó là myscript env FOO=bar baz
được thực thi exec env FOO=bar baz
và hoàn toàn hợp lệ.
FOO=bar exec baz
mặc dù, vì vậy bạn không cần env
ở điểm cuối cùng của bạn.
exec
một cái gì đó, nó sử dụng môi trường hiện tại của bạn?
sudo FOO=bar baz
chuyển các biến môi trường mà không cần env
.
FOO=bar
vào tập lệnh. Nếu FOO
không phải lúc nào cũng vậy bar
, tôi không muốn mã hóa nó, và thay vào đó hãy chuyển nó vào.
exec
, chẳng hạn như FOO=bar exec baz
.
Trong ví dụ cụ thể này, không có sự khác biệt hiệu quả, giả sử vỏ của bạn là vỏ tương thích POSIX và giả sử baz
là vỏ có thể thực thi và không phải là vỏ dựng sẵn.
Ví dụ , nếu vỏ của bạn không phải là vỏ tương thích POSIX, csh
hoặc tcsh
cú pháp
FOO=bar baz
không hoạt động và không có cú pháp shell tương đương. Đối với các shell đó, env
lệnh là cách duy nhất để ghi đè hoặc chèn các biến môi trường cho một lệnh.
Nếu baz
là shell dựng sẵn, giả sử fc
, chẳng hạn, env
sẽ không cho kết quả tương tự, vì env
đang thực hiện một quy trình mới thay vì được chạy trực tiếp bởi shell lệnh. Hơn nữa, không có fc
khả năng thực thi, nó chỉ có thể được chạy dưới dạng shell dựng vì cách nó tương tác với môi trường shell, và vì vậy env
sẽ không bao giờ hoạt động với một nội dung như vậy fc
.
Ngoài ra, env
cung cấp -i
tùy chọn, cho phép bạn bắt đầu một lệnh trong môi trường trống chỉ với một bộ biến môi trường được chỉ định. Vì vậy, env
có thể rất hữu ích để bắt đầu các quy trình trong môi trường vệ sinh, ví dụ
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcsh
tôi sẽ viết (setenv FOO bar; baz)
để có được chức năng tương đương.
Ngoài những gì đã được nói
VAR=value cmd args > redirs
là một tính năng shell (Bourne / POSIX), bạn bị giới hạn trong tên của các biến môi trường mà bạn chuyển đến cmd
. Chúng phải là tên biến shell hợp lệ và không được là biến chỉ đọc hoặc biến đặc biệt đối với shell.
Chẳng hạn, bạn không thể làm:
1=foo cmd
Hoặc là
+++=bar cmd
bash
không cho phép bạn làm:
SHELLOPTS=xtrace cmd
Trong khi bạn có thể làm:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(không phải là bạn muốn hoặc nên muốn làm điều đó). Hoặc là:
env SHELLOPTS=xtrace cmd
(Đôi khi tôi cần phải làm điều đó).
Lưu ý rằng với env
bạn vẫn không thể vượt qua chuỗi biến môi trường không chứa =
(không phải là bạn muốn làm điều đó).
Một cách sử dụng env
là cho phép $PATH
tìm kiếm các tệp thực thi trong các dòng shebang (vì env
xem xét $PATH
khi tìm kiếm tệp thực thi). Điều này rất hữu ích nếu tệp thực thi bạn muốn gọi có thể ở các vị trí khác nhau trên các máy khác nhau. Ví dụ,
#!/usr/bin/env perl
trong dòng đầu tiên của tập lệnh có tập bit thực thi sẽ thực thi tập lệnh này với Perl bất kể nó được cài đặt /usr/bin/perl
trong /usr/local/bin/perl
hoặc ở một nơi hoàn toàn khác, miễn là thư mục nằm trong đường dẫn.
Tất nhiên, tìm kiếm đường dẫn đi kèm với rủi ro gia tăng, nhưng sau đó, rủi ro không lớn hơn nếu bạn đã viết rõ ràng perl yourscript.pl
, điều này cũng tìm kiếm perl trong đường dẫn tìm kiếm.
Một lần khác khi env
thực sự hữu ích là nếu bạn muốn kiểm soát hoàn toàn môi trường. Tôi chạy một chương trình máy chủ (Informix, trong trường hợp bạn không thể đoán) có môi trường mà tôi muốn kiểm soát hoàn toàn. Tôi chạy nó bằng cách sử dụng env
ở cuối tập lệnh, đặt một loạt các biến thành các giá trị chính xác:
env -i HOME="$IXD" \
INFORMIXDIR="$IXD" \
INFORMIXSERVER="$IXS" \
${IXC:+INFORMIXCONCSMCFG="$IXC"} \
${IXH:+INFORMIXSQLHOSTS="$IXH"} \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG="onconfig.$IXS" \
PATH="/bin:/usr/bin:$IXD/bin" \
SHELL=/bin/ksh \
TZ=UTC0 \
$ONINIT "$@"
Các -i
tùy chọn hạ gục các môi trường hiện tại. Các VAR=value
tùy chọn tiếp theo đặt các biến môi trường mà tôi muốn đặt; tên của chương trình nằm trong $ONINIT
và bất kỳ đối số dòng lệnh nào được truyền qua nguyên văn với "$@"
.
Cấu ${IXH:+INFORMIXSQLHOSTS="$IXH"}
trúc chỉ chuyển INFORMIXSQLHOSTS="$IXH"
đến env
nếu $IXH
được đặt thành giá trị không trống.