Trước hết, bạn nên rất ít khi sử dụng $*
và bạn hầu như luôn luôn sử dụng "[email protected]"
để thay thế. Có một số câu hỏi ở đây về SO, giải thích về các lý do tại sao.
Thứ hai - lệnh env
có hai cách sử dụng chính. Một là in môi trường hiện tại; khác là hoàn toàn kiểm soát môi trường của một lệnh khi nó được chạy. Việc sử dụng thứ ba, mà bạn đang thể hiện, là để sửa đổi môi trường, nhưng thẳng thắn không có nhu cầu cho điều đó - các vỏ có khả năng xử lý điều đó cho bạn.
Chế độ 1:
env
Chế độ 2:
env -i HOME=$HOME PATH=$PREPENDPATH:$PATH ... command args
Phiên bản này hủy bỏ tất cả các biến môi trường kế thừa và chạy command
với chính môi trường được thiết lập bởi các tùy chọn ENVVAR = giá trị.
Chế độ thứ ba - sửa đổi môi trường - ít quan trọng hơn vì bạn có thể làm điều đó tốt với vỏ thông thường (văn minh). (. Điều đó có nghĩa "không C shell" - một lần nữa, có những câu hỏi khác về SO với câu trả lời giải thích đó) Ví dụ, bạn hoàn toàn tốt có thể làm:
#!/bin/bash
export PATH=${PREPENDPATH:?}:$PATH
exec python "[email protected]"
này nhấn mạnh rằng $PREPENDPATH
được đặt thành một phi chuỗi rỗng trong môi trường, sau đó thêm nó vào $PATH
và xuất cài đặt PATH mới. Sau đó, sử dụng PATH mới, nó thực thi chương trình python
với các đối số có liên quan. Các exec
thay thế kịch bản shell với python
. Lưu ý rằng điều này hoàn toàn khác với:
#!/bin/bash
PATH=${PREPENDPATH:?}:$PATH exec python "[email protected]"
Bề ngoài, điều này giống nhau. Tuy nhiên, điều này sẽ thực thi python
được tìm thấy trên PATH đã tồn tại trước đó, mặc dù với giá trị mới của PATH trong môi trường của quá trình. Vì vậy, trong ví dụ, bạn sẽ kết thúc thực hiện Python từ /usr/bin
và không phải là một từ /home/pi/prepend/bin
.
Trong trường hợp của bạn, tôi có thể không sử dụng env
và sẽ chỉ sử dụng một biến thể phù hợp của tập lệnh với xuất rõ ràng.
Lệnh env
không bình thường vì lệnh này không nhận dạng dấu gạch ngang kép để tách các tùy chọn khỏi phần còn lại của lệnh. Điều này một phần vì nó không có nhiều lựa chọn, và một phần vì không rõ liệu các tùy chọn ENVVAR = value có đến trước hoặc sau dấu gạch ngang kép hay không.
Tôi thực sự có một loạt các tập lệnh để chạy (các phiên bản khác nhau) của một máy chủ cơ sở dữ liệu. Những kịch bản thực sự sử dụng env
(và một loạt các chương trình cây nhà lá vườn) để kiểm soát môi trường của máy chủ:
#!/bin/ksh
#
# @(#)$Id: boot.black_19.sh,v 1.3 2008/06/25 15:44:44 jleffler Exp $
#
# Boot server black_19 - IDS 11.50.FC1
IXD=/usr/informix/11.50.FC1
IXS=black_19
cd $IXD || exit 1
IXF=$IXD/do.not.start.$IXS
if [ -f $IXF ]
then
echo "$0: will not start server $IXS because file $IXF exists" 1>&2
exit 1
fi
ONINIT=$IXD/bin/oninit.$IXS
if [ ! -f $ONINIT ]
then ONINIT=$IXD/bin/oninit
fi
tmpdir=$IXD/tmp
DAEMONIZE=/work1/jleffler/bin/daemonize
stdout=$tmpdir/$IXS.stdout
stderr=$tmpdir/$IXS.stderr
if [ ! -d $tmpdir ]
then asroot -u informix -g informix -C -- mkdir -p $tmpdir
fi
# Specialized programs carried to extremes:
# * asroot sets UID and GID values and then executes
# * env, which sets the environment precisely and then executes
# * daemonize, which makes the process into a daemon and then executes
# * oninit, which is what we really wanted to run in the first place!
# NB: daemonize defaults stdin to /dev/null and could set umask but
# oninit dinks with it all the time so there is no real point.
# NB: daemonize should not be necessary, but oninit doesn't close its
# controlling terminal and therefore causes cron-jobs that restart
# it to hang, and interactive shells that started it to hang, and
# tracing programs.
# ??? Anyone want to integrate truss into this sequence?
asroot -u informix -g informix -C -a dbaao -a dbsso -- \
env -i HOME=$IXD \
INFORMIXDIR=$IXD \
INFORMIXSERVER=$IXS \
INFORMIXCONCSMCFG=$IXD/etc/concsm.$IXS \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG=onconfig.$IXS \
PATH=/usr/bin:$IXD/bin \
SHELL=/usr/bin/ksh \
TZ=UTC0 \
$DAEMONIZE -act -d $IXD -o $stdout -e $stderr -- \
$ONINIT "[email protected]"
case "$*" in
(*v*) track-oninit-v $stdout;;
esac
Đây là thông tin hữu ích, nhưng như OP nói,/kernel của mình sẽ không chạy không các tệp nhị phân (chẳng hạn như các bash stubs mà bạn cung cấp) làm phần tử đầu tiên của một dòng shebang. Mỏ sẽ không; cụ thể, hạt nhân âm thầm không chạy kịch bản với dòng shebang có vấn đề trong trình thông dịch mong muốn (không nhị phân), và sau đó trình bao của tôi sẽ cố gắng chạy tập lệnh thay thế. (Understading của tôi là đây là một hành vi vỏ cũ thời gian mà nhiều vỏ giữ lại.) – dubiousjim
Tôi không hiểu những gì bạn đang nói? Bạn đang tuyên bố rằng có (vẫn) shell hoặc hạt nhân sẽ không xử lý '#!/Bin/bash' hoặc' #!/Bin/ksh' làm dòng đầu tiên của tập lệnh? Tôi không tuyên bố hoặc cho thấy rằng bạn có thể sử dụng '#!/Some/script' như một shebang. –
Không xác nhận quyền sở hữu đầu tiên. Câu hỏi của OP là về câu hỏi thứ hai, mặc dù: anh ta/cô ấy hỏi "Hạt nhân sẽ làm gì nếu bạn gắn một kịch bản lệnh shell vào dòng shebang?" và sau đó báo cáo các vấn đề phát sinh từ việc sử dụng env.1 như một dòng shebang, trong đó env.1 là một tập lệnh. (Khi nó xảy ra, nó đang tìm kiếm các cuộc thảo luận về những hạn chế về các dòng shebang mang tôi đến đây. Và tôi đã tìm thấy bài đăng của bạn có thông tin hữu ích, vì vậy cảm ơn vì đã đóng góp nó. rằng những gì bạn thảo luận không giúp vượt qua giới hạn mà OP đã gặp phải.) – dubiousjim