ความแตกต่างระหว่างคำสั่งคืออะไร
$ env FOO=bar baz
และ
$ FOO=bar baz
มีผลกระทบอะไรenv
บ้าง
ความแตกต่างระหว่างคำสั่งคืออะไร
$ env FOO=bar baz
และ
$ FOO=bar baz
มีผลกระทบอะไรenv
บ้าง
คำตอบ:
พวกมันมีหน้าที่เทียบเท่า
แตกต่างที่สำคัญคือการที่env FOO=bar baz
เกี่ยวข้องกับการเรียกกระบวนการตัวกลางระหว่างเปลือกและbaz
ที่เช่นเดียวกับเปลือกจะเรียกโดยตรงFOO=bar baz
ดังนั้นในเรื่องที่เป็นที่ต้องการbaz
FOO=bar baz
สถานการณ์เดียวที่ฉันพบว่าตัวเองกำลังใช้env FOO=bar
อยู่คือที่ฉันต้องส่งคำสั่งไปยังคำสั่งอื่น
เป็นตัวอย่างเฉพาะสมมติว่าฉันมีสคริปต์ตัวตัดคำที่ทำการแก้ไขบางอย่างของสภาพแวดล้อมและจากนั้นเรียกexec
ใช้คำสั่งที่ส่งผ่านไปเช่น:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
หากคุณดำเนินการตามmyscript FOO=bar baz
นั้นexec
จะทำให้เกิดข้อผิดพลาดตามที่exec FOO=bar baz
ไม่ถูกต้อง
แต่คุณเรียกมันว่าmyscript env FOO=bar baz
สิ่งที่ถูกดำเนินการexec env FOO=bar baz
และมีผลสมบูรณ์
FOO=bar exec baz
ดังนั้นคุณไม่จำเป็นต้องenv
อยู่ในจุดสุดท้าย
exec
บางสิ่งมันใช้สภาพแวดล้อมปัจจุบันของคุณหรือไม่?
sudo FOO=bar baz
env
FOO=bar
สคริปต์ หากFOO
ไม่เสมอbar
ไปฉันไม่ต้องการเขียนโค้ดอย่างหนักและส่งผ่านแทน
exec
FOO=bar exec baz
ในตัวอย่างนี้ไม่มีความแตกต่างที่มีประสิทธิภาพสมมติว่าเชลล์ของคุณเป็นเชลล์ที่เข้ากันได้กับ POSIX และสมมติว่าbaz
เป็นไฟล์ที่เรียกใช้งานได้และไม่ใช่เชลล์ในตัว
หากเชลล์ของคุณไม่ใช่เชลล์ที่เข้ากันได้กับ POSIX ตัวอย่างเช่นcsh
หรือtcsh
ไวยากรณ์
FOO=bar baz
ไม่ทำงานและไม่มีไวยากรณ์เชลล์เทียบเท่า สำหรับเชลล์เหล่านั้นenv
คำสั่งเป็นวิธีเดียวที่จะแทนที่หรือฉีดตัวแปรสภาพแวดล้อมสำหรับคำสั่งเดียว
ถ้าbaz
เป็น shell builtin เราจะfc
ยกตัวอย่างเช่นแล้วenv
จะไม่ให้ผลลัพธ์เดียวกันเพราะenv
กำลังประมวลผลกระบวนการใหม่แทนที่จะเรียกใช้โดยตรงโดย command command นอกจากนี้ยังไม่มีการfc
ปฏิบัติการจะสามารถทำงานเป็นเพียงเปลือก builtin เพราะวิธีการที่จะมีปฏิสัมพันธ์กับสภาพแวดล้อมเปลือกและอื่น ๆenv
จะไม่เคยทำงานร่วมกับ builtin fc
เช่น
นอกจากนี้ยังenv
มี-i
ตัวเลือกซึ่งช่วยให้คุณสามารถเริ่มคำสั่งในสภาพแวดล้อมที่ว่างเปล่าที่มีชุดของตัวแปรสภาพแวดล้อมที่ระบุเท่านั้น ดังนั้นenv
จะมีประโยชน์มากสำหรับกระบวนการเริ่มต้นในสภาพแวดล้อมที่ผ่านการฆ่าเชื้อเช่น
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcsh
ฉันจะเขียน(setenv FOO bar; baz)
เพื่อรับฟังก์ชั่นที่เทียบเท่า
นอกจากสิ่งที่ได้กล่าวไปแล้ว
VAR=value cmd args > redirs
เป็นเปลือกคุณลักษณะ (บอร์น / POSIX) คุณจะ จำกัด cmd
ในชื่อของตัวแปรสภาพแวดล้อมที่คุณส่งผ่านไปยัง พวกเขาจะต้องเป็นชื่อตัวแปรเชลล์ที่ถูกต้องและต้องไม่เป็นตัวแปรแบบอ่านอย่างเดียวหรือพิเศษสำหรับเชลล์
ตัวอย่างเช่นคุณไม่สามารถทำได้:
1=foo cmd
หรือ
+++=bar cmd
bash
ไม่อนุญาตให้คุณทำ:
SHELLOPTS=xtrace cmd
ในขณะที่คุณสามารถทำได้:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(ไม่ใช่ที่คุณต้องการหรือควรจะทำอย่างนั้น) หรือ:
env SHELLOPTS=xtrace cmd
(บางครั้งฉันต้องทำอย่างนั้น)
โปรดทราบว่าในขณะที่env
คุณยังไม่สามารถผ่านสตริงตัวแปรสภาพแวดล้อมที่ไม่มี=
(ไม่ใช่ว่าคุณต้องการทำเช่นนั้น)
การใช้งานอย่างหนึ่งenv
คือการอนุญาตให้$PATH
ค้นหาไฟล์ที่เรียกใช้งานได้ในแนว Shebang (เนื่องจากenv
พิจารณา$PATH
เมื่อค้นหาไฟล์ที่เรียกทำงานได้) สิ่งนี้มีประโยชน์หากปฏิบัติการที่คุณต้องการเรียกใช้อาจอยู่ในสถานที่ที่แตกต่างกันบนเครื่องที่แตกต่างกัน ตัวอย่างเช่น,
#!/usr/bin/env perl
ในบรรทัดแรกของสคริปต์ที่มีชุดบิตที่เรียกทำงานได้จะเรียกใช้งานสคริปต์นี้ด้วย Perl ไม่ว่าจะติดตั้งใน/usr/bin/perl
หรือใน/usr/local/bin/perl
หรือในสถานที่ที่แตกต่างอย่างสิ้นเชิงตราบใดที่ไดเรกทอรีอยู่ในเส้นทาง
แน่นอนว่าการค้นหาเส้นทางมาพร้อมกับความเสี่ยงที่เพิ่มขึ้น แต่จากนั้นความเสี่ยงนั้นไม่ใหญ่กว่าถ้าคุณเขียนไว้อย่างชัดเจนperl yourscript.pl
ซึ่งจะค้นหา Perl ในเส้นทางการค้นหาด้วย
อีกครั้งเมื่อenv
มีประโยชน์จริง ๆ คือถ้าคุณต้องการควบคุมสภาพแวดล้อมอย่างสมบูรณ์ ฉันเรียกใช้โปรแกรมเซิร์ฟเวอร์ (Informix ในกรณีที่คุณไม่สามารถเดาได้) ซึ่งมีสภาพแวดล้อมที่ฉันต้องการควบคุมอย่างสมบูรณ์ ฉันรันโดยใช้env
ที่ส่วนท้ายของสคริปต์ซึ่งตั้งค่าตัวแปรให้เป็นค่าที่ถูกต้อง:
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 "$@"
-i
ตัวเลือก zaps สภาพแวดล้อมที่มีอยู่ VAR=value
ตัวเลือกที่ตามมาตั้งค่าตัวแปรสภาพแวดล้อมที่ฉันต้องการตั้งค่า ชื่อของโปรแกรมที่อยู่ใน$ONINIT
และอาร์กิวเมนต์บรรทัดคำสั่งใด ๆ "$@"
จะถูกส่งผ่านคำต่อคำกับ
การ${IXH:+INFORMIXSQLHOSTS="$IXH"}
สร้างจะผ่านINFORMIXSQLHOSTS="$IXH"
ไปenv
หาก$IXH
ถูกตั้งค่าเป็นค่าที่ไม่ว่างเปล่า