Untuk env atau tidak untuk env


32

Apa perbedaan antara perintah itu?

$ env FOO=bar baz

dan

$ FOO=bar baz

Apa efeknya env?


4
Semacam pertanyaan sampingan, tapi apa fitur yang dipanggil saat Anda mengatur variabel lingkungan untuk satu perintah tunggal seperti itu? Saya selalu kesulitan menemukan info tentang ini karena saya tidak tahu apa namanya.
John Cromartie

1
@ JohnCromartie, Anda harus menanyakan itu sebagai pertanyaan.
cjm

1
Untuk bash, didokumentasikan di sini: gnu.org/software/bash/manual/…
glenn jackman

2
@JohnCromartie Ini adalah komponen opsional dari setiap perintah shell, jadi itu ada di bagian "Perintah Sederhana" di sebagian besar manual shell. Untuk POSIX, itu ada di sini . glenn menautkan bagian analog dari bash manual untuk Anda.
jw013

Mengatur variabel yang tidak ada melalui tugas membuat variabel shell. Mengaturnya melalui ENV atau mengekspor variabel mendorong variabel ke lingkungan eksekusi shell. Mengubah nilai variabel yang ada akan memperbarui nilai lingkungan eksekusi jika ada, jika tidak mengubahnya dalam variabel internal shell.
Johan

Jawaban:


26

Mereka setara secara fungsional.

Perbedaan utama adalah bahwa env FOO=bar bazmelibatkan proses perantara antara shell dan baz, FOO=bar bazsedangkan shell secara langsung memanggil baz.
Jadi dalam hal itu, FOO=bar bazlebih disukai.

Satu-satunya situasi di mana saya menemukan diri saya menggunakan env FOO=baradalah di mana saya harus meneruskan perintah ke perintah lain.
Sebagai contoh khusus, katakanlah saya memiliki skrip wrapper yang melakukan beberapa modifikasi lingkungan, dan kemudian memanggil execperintah yang diteruskan ke sana, seperti:

#!/bin/bash
FOO=bob
some stuff
exec "$@"

Jika Anda menjalankannya sebagai myscript FOO=bar baz, maka execakan membuang kesalahan karena exec FOO=bar baztidak valid.
Alih-alih Anda menyebutnya sebagai myscript env FOO=bar bazyang dieksekusi sebagai exec env FOO=bar baz, dan sangat valid.


1
Anda dapat melakukannya FOO=bar exec baz, jadi Anda tidak perlu envpada poin terakhir Anda.
Stéphane Chazelas

Ketika Anda melakukan execsesuatu, apakah itu menggunakan lingkungan Anda saat ini?
glenn jackman

1
Ditto @StephaneChazelas, dan Anda juga bisa sudo FOO=bar bazmelewatkan variabel lingkungan tanpa perlu env.
Mike Miller

1
@StephaneChazelas yang hanya berfungsi jika saya ingin memasukkan FOO=barskrip. Jika FOOtidak selalu bar, saya tidak ingin memasukkan kode yang sulit, dan malah meneruskannya.
Patrick

@glennjackman ya itu, asalkan variabel diekspor atau diteruskan sebelum exec, seperti FOO=bar exec baz.
Patrick

14

Dalam contoh khusus ini, tidak ada perbedaan yang efektif, dengan asumsi shell Anda adalah shell yang kompatibel dengan POSIX, dan dengan asumsi itu bazadalah executable dan bukan shell builtin.

Jika shell Anda bukan shell yang kompatibel dengan POSIX, misalnya cshatau tcsh, sintaks

FOO=bar baz

tidak bekerja, dan tidak ada sintaks shell yang setara. Untuk cangkang tersebut, envperintah adalah satu-satunya cara untuk mengganti atau menyuntikkan variabel lingkungan untuk satu perintah.

Jika bazshell dibangun, katakanlah fcmisalnya, maka envtidak akan memberikan hasil yang sama, karena envmenjalankan proses baru alih-alih dijalankan langsung oleh perintah shell. Selain itu, tidak ada yang fcdapat dieksekusi, itu hanya dapat dijalankan sebagai shell builtin karena cara itu berinteraksi dengan lingkungan shell, dan dengan demikian tidakenv akan pernah bekerja dengan builtin like fc.

Selain itu, envmenawarkan -iopsi, yang memungkinkan Anda untuk memulai perintah di lingkungan kosong dengan hanya satu set variabel lingkungan yang ditentukan. Jadi envbisa sangat berguna untuk memulai proses di lingkungan yang disanitasi, misalnya

env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz

Ketika saya biasa menggunakan tcshsaya akan menulis (setenv FOO bar; baz)untuk mendapatkan fungsi yang setara.
Barmar

6

Selain apa yang sudah dikatakan

VAR=value cmd args > redirs

menjadi fitur shell (Bourne / POSIX), Anda dibatasi atas nama variabel lingkungan yang Anda lewatkan cmd. Mereka harus nama variabel shell yang valid dan tidak boleh hanya-baca atau variabel khusus ke shell.

Misalnya, Anda tidak dapat melakukan:

1=foo cmd

Atau

+++=bar cmd

bash tidak memungkinkan Anda untuk melakukan:

SHELLOPTS=xtrace cmd

Meskipun Anda dapat melakukan:

env 1=foo cmd
env +++=bar cmd
env '=baz' cmd

(bukan yang Anda inginkan atau ingin lakukan itu). Atau:

env SHELLOPTS=xtrace cmd

(Terkadang saya perlu melakukan itu).

Perhatikan bahwa dengan envAnda masih tidak dapat meneruskan string variabel lingkungan yang tidak mengandung =(bukan bahwa Anda juga ingin melakukannya).


2

Salah satu penggunaannya envadalah untuk memungkinkan $PATHpencarian executable di baris shebang (karena envmempertimbangkan $PATHsaat mencari executable). Ini berguna jika executable yang ingin Anda panggil mungkin ada di tempat yang berbeda pada mesin yang berbeda. Sebagai contoh,

#!/usr/bin/env perl

di baris pertama skrip dengan bit set yang dapat dieksekusi akan mengeksekusi skrip ini dengan Perl tidak peduli apakah itu dipasang di /usr/bin/perlatau di /usr/local/bin/perlatau di tempat yang sama sekali berbeda, selama direktori berada di jalur.

Tentu saja pencarian jalur tersebut disertai dengan risiko tambahan, tetapi kemudian, risikonya tidak lebih besar daripada jika Anda telah menulisnya secara eksplisit perl yourscript.pl, yang juga mencari perl di jalur pencarian.


2

Lain waktu ketika envbenar-benar berguna adalah jika Anda ingin mengendalikan lingkungan sepenuhnya. Saya menjalankan program server (Informix, jika Anda tidak bisa menebak) yang lingkungannya ingin saya kendalikan sepenuhnya. Saya menjalankannya menggunakan envdi akhir skrip yang mengatur sekelompok variabel ke nilai yang benar:

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 "$@"

The -ipilihan zaps lingkungan yang ada. VAR=valueOpsi selanjutnya mengatur variabel lingkungan yang ingin saya atur; nama program $ONINIT, dan argumen baris perintah apa pun dilewatkan melalui kata demi kata "$@".

The ${IXH:+INFORMIXSQLHOSTS="$IXH"}membangun hanya melewati INFORMIXSQLHOSTS="$IXH"ke envjika $IXHdiatur ke nilai non-kosong.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.