ความแตกต่างระหว่างสองคำสั่งenvและprintenvคืออะไร? _พวกเขาทั้งสองแสดงตัวแปรสภาพแวดล้อมและการส่งออกจะตรงเดียวกันนอกเหนือจาก
มีเหตุผลทางประวัติศาสตร์หรือไม่ที่มีสองคำสั่งแทนที่จะเป็นหนึ่งคำสั่ง?
ความแตกต่างระหว่างสองคำสั่งenvและprintenvคืออะไร? _พวกเขาทั้งสองแสดงตัวแปรสภาพแวดล้อมและการส่งออกจะตรงเดียวกันนอกเหนือจาก
มีเหตุผลทางประวัติศาสตร์หรือไม่ที่มีสองคำสั่งแทนที่จะเป็นหนึ่งคำสั่ง?
คำตอบ:
มีเหตุผลทางประวัติศาสตร์หรือไม่ที่มีสองคำสั่งแทนที่จะเป็นหนึ่งคำสั่ง?
มีลักษณะประวัติศาสตร์เพียง
printenvคำสั่งเวอร์ชันแรกในปี 1979 สำหรับ BSDenvคำสั่งในปี 1980envในปี 1986envในปี 1988printenvในปี 1988printenvในปี 1989printenvและenvในปี 1991โปรดทราบว่า "ติดตาม" ไม่ได้หมายความว่าซอร์สโค้ดเหมือนกันอาจเป็นไปได้ว่าพวกเขาจะถูกเขียนใหม่เพื่อหลีกเลี่ยงการฟ้องร้องดำเนินคดี
ดังนั้นสาเหตุที่คำสั่งทั้งสองนั้นมีอยู่เพราะเมื่อจอยเขียนprintenvตอนนั้นสิ่งที่envยังไม่เกิดขึ้น หลังจากการผสาน / ความเข้ากันได้เป็นเวลา 10 ปีและ GNU เจอแล้วตอนนี้คุณเห็นคำสั่งที่คล้ายกันทั้งสองที่หน้าเดียวกัน
ประวัตินี้ระบุไว้ดังต่อไปนี้: (ฉันพยายามที่จะลดคำตอบให้เหลือเพียง 2 ซอร์สโค้ดที่สำคัญที่นี่ส่วนที่เหลือคุณสามารถคลิกลิงค์ที่แนบมาเพื่อดู)
[ฤดูใบไม้ร่วงปี 2518]
เมื่อถึงฤดูใบไม้ร่วงปี 2518 นักศึกษาบัณฑิตสองคนที่ไม่มีใครสังเกตเห็นคือ Bill Joy และ Chuck Haley; พวกเขาทั้งสองสนใจในระบบใหม่ทันที เริ่มแรกพวกเขาเริ่มทำงานกับระบบปาสคาลที่ ธ อมป์สันแฮ็คด้วยกันขณะที่แขวนอยู่รอบ ๆ ห้องเครื่อง 11/70
[1977]
Joy เริ่มรวบรวม Berkeley Software Distribution (1BSD) ครั้งแรกซึ่งเปิดตัวเมื่อวันที่ 9 มีนาคม 2521 // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[กุมภาพันธ์, 1979]
2522 (ดู "บิลจอย UCB กุมภาพันธ์ 2522") / 2523 (ดู "ลิขสิทธิ์ [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? ยื่น = 2.11BSD / src / เลือดจากสายสะดือ / printenv.c
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif not lint
#ifndef lint
static char sccsid[] = "@(#)printenv.c 5.1 (Berkeley) 5/31/85";
#endif not lint
/*
* printenv
*
* Bill Joy, UCB
* February, 1979
*/
extern char **environ;
main(argc, argv)
int argc;
char *argv[];
{
register char **ep;
int found = 0;
argc--, argv++;
if (environ)
for (ep = environ; *ep; ep++)
if (argc == 0 || prefix(argv[0], *ep)) {
register char *cp = *ep;
found++;
if (argc) {
while (*cp && *cp != '=')
cp++;
if (*cp == '=')
cp++;
}
printf("%s\n", cp);
}
exit (!found);
}
prefix(cp, dp)
char *cp, *dp;
{
while (*cp && *dp && *cp == *dp)
cp++, dp++;
if (*cp == 0)
return (*dp == '=');
return (0);
}
[1979]
ยากที่จะตรวจสอบเผยแพร่ใน 2BSD หรือ 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD คำสั่ง printenv ปรากฏใน 3.0 BSD // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD เปิดตัวในปี 1979 // rf: http://gunkies.org/wiki/3_BSD
2BSD คำสั่ง printenv ปรากฏเป็นครั้งแรกใน 2BSD // rf: http://man.openbsd.org/printenv.1
[มิถุนายน 1980]
UNIX รีลีส 3.0 หรือ "UNIX System III" // rf: ftp://pdp11.org.ru/pub/unix-archive/PDP-11/Distribution/usdl/SysIII/
[xiaobai@xiaobai pdp11v3]$ sudo grep -rni printenv . //no such printenv exist.
[xiaobai@xiaobai pdp11v3]$ sudo find . -iname '*env*'
./sys3/usr/src/lib/libF77/getenv_.c
./sys3/usr/src/lib/libc/vax/gen/getenv.c
./sys3/usr/src/lib/libc/pdp11/gen/getenv.c
./sys3/usr/src/man/man3/getenv.3c
./sys3/usr/src/man/docs/c_env
./sys3/usr/src/man/docs/mm_man/s03envir
./sys3/usr/src/man/man7/environ.7
./sys3/usr/src/man/man1/env.1
./sys3/usr/src/cmd/env.c
./sys3/bin/env
[xiaobai@xiaobai pdp11v3]$ man ./sys3/usr/src/man/man1/env.1 | cat //but got env already
ENV(1) General Commands Manual ENV(1)
NAME
env - set environment for command execution
SYNOPSIS
env [-] [ name=value ] ... [ command args ]
DESCRIPTION
Env obtains the current environment, modifies it according to its arguments, then executes the command with the modified environment. Arguments of the form
name=value are merged into the inherited environment before the command is executed. The - flag causes the inherited environment to be ignored completely,
so that the command is executed with exactly the environment specified by the arguments.
If no command is specified, the resulting environment is printed, one name-value pair per line.
SEE ALSO
sh(1), exec(2), profile(5), environ(7).
ENV(1)
[xiaobai@xiaobai pdp11v3]$
[xiaobai@xiaobai pdp11v3]$ cat ./sys3/usr/src/cmd/env.c //diff with http://minnie.tuhs.org/cgi-bin/utree.pl?file=pdp11v/usr/src/cmd/env.c version 1.4, you will know this file is slightly older, so we can concluded that this file is "env.c version < 1.4"
/*
* env [ - ] [ name=value ]... [command arg...]
* set environment, then execute command (or print environment)
* - says start fresh, otherwise merge with inherited environment
*/
#include <stdio.h>
#define NENV 100
char *newenv[NENV];
char *nullp = NULL;
extern char **environ;
extern errno;
extern char *sys_errlist[];
char *nvmatch(), *strchr();
main(argc, argv, envp)
register char **argv, **envp;
{
argc--;
argv++;
if (argc && strcmp(*argv, "-") == 0) {
envp = &nullp;
argc--;
argv++;
}
for (; *envp != NULL; envp++)
if (strchr(*envp, '=') != NULL)
addname(*envp);
while (*argv != NULL && strchr(*argv, '=') != NULL)
addname(*argv++);
if (*argv == NULL)
print();
else {
environ = newenv;
execvp(*argv, argv);
fprintf(stderr, "%s: %s\n", sys_errlist[errno], *argv);
exit(1);
}
}
addname(arg)
register char *arg;
{
register char **p;
for (p = newenv; *p != NULL && p < &newenv[NENV-1]; p++)
if (nvmatch(arg, *p) != NULL) {
*p = arg;
return;
}
if (p >= &newenv[NENV-1]) {
fprintf(stderr, "too many values in environment\n");
print();
exit(1);
}
*p = arg;
return;
}
print()
{
register char **p = newenv;
while (*p != NULL)
printf("%s\n", *p++);
}
/*
* s1 is either name, or name=value
* s2 is name=value
* if names match, return value of s2, else NULL
*/
static char *
nvmatch(s1, s2)
register char *s1, *s2;
{
while (*s1 == *s2++)
if (*s1++ == '=')
return(s2);
if (*s1 == '\0' && *(s2-1) == '=')
return(s2);
return(NULL);
}
[xiaobai@xiaobai pdp11v3]$
[1985]
BSD คู่มือแรก printenv // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 แต่ฉันไม่พบคู่มือที่เกี่ยวข้องกับ env ที่ใกล้เคียงที่สุดคือ getenv และ environ // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
รุ่นแรกของ GNU env// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/env.c
[1987]
MINIX เปิดตัวครั้งแรก // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum
[1988]
BSD 1st env.c // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/usr.sbin/cron/env.c
/* Copyright 1988,1990,1993,1994 by Paul Vixie
* All rights reserved
[4 ตุลาคม 2531]
MINIX เวอร์ชัน 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 / minix/commands/printenv.c //printenv.c มีอยู่แล้ว
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
รุ่นแรกของ GNU printenvอ้างถึง [12 สิงหาคม 1993]
[16 กรกฎาคม 1991]
"Shellutils" - โปรแกรมอรรถประโยชน์การเขียนโปรแกรมเชลล์ของ GNU 1.0 เปิดตัว // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
โปรแกรมในแพ็คเกจนี้คือ:
basename date dirname envกลุ่ม expr id logname pathchk printenv printf sleep tee tty whoami ใช่ดี nohup stty uname
[12 สิงหาคม 2536]
printenv.c // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/printenv.c
, GNU Shell Utilities 1.8 // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/ รุ่นที่
/* printenv -- print all or part of environment
Copyright (C) 1989, 1991 Free Software Foundation.
...
[1993]
printenv.c ซึ่งพบในซอร์สโค้ด DSLinux ในปี 2549 // rf: (Google) แคช: mailman.dslinux.in-berlin.de/pipermail/dslinux-commit-dslinux.in-berlin.de/2006-August/000578 HTML
--- NEW FILE: printenv.c ---
/*
* Copyright (c) 1993 by David I. Bell
[พฤศจิกายน 1993]
FreeBSD เวอร์ชันแรกเปิดตัวแล้ว // rf: https://en.wikipedia.org/wiki/FreeBSD
[กันยายน 1, 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
fileutils ของ GNU, textutils และ sh-utils (ดู "Shellutils" ที่ 16 กรกฎาคม 1991 ข้างบน) แพ็คเกจได้ถูกรวมเข้าเป็นหนึ่งเดียวเรียกว่า GNU coreutils
โดยรวมแล้วenvใช้กรณีเปรียบเทียบกับprintenv:
printenvสามารถทำเช่นเดียวกันenablecmd ด้วยตั้งค่าตัวแปร แต่ไม่มีจุดหมายเนื่องจากเชลล์บางตัวสามารถทำได้โดยไม่มีenvเช่น
$ HOME = / dev HOME = / tmp USER = root / bin / bash -c "cd ~; pwd"
tmp /
#!/usr/bin/env pythonส่วนหัว แต่ยังไม่สามารถพกพาenvได้หากไม่อยู่ใน / usr / bin
env -iปิดการใช้งาน env ทั้งหมด ฉันพบว่ามีประโยชน์ในการหาตัวแปรสภาพแวดล้อมที่สำคัญสำหรับบางโปรแกรมเพื่อให้ทำงานcrontabได้ เช่น [1] ในโหมดโต้ตอบให้เรียกใช้declare -p > /tmp/d.shเพื่อเก็บตัวแปรแอตทริบิวต์ [2] ใน/tmp/test.shเขียน: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg[3] ตอนนี้เรียกใช้env -i bash /tmp/test.sh[4] หากประสบความสำเร็จในการแสดงภาพให้ลบตัวแปรครึ่งหนึ่งใน/tmp/d.shแล้วเรียกใช้env -i bash /tmp/test.shอีกครั้ง หากสิ่งที่ล้มเหลวยกเลิกการทำมัน ทำซ้ำขั้นตอนนี้เพื่อ จำกัด ให้แคบลง [5] ในที่สุดฉันก็eogต้องออก$DISPLAYไปทำงานcrontabและถ้าขาดไป$DBUS_SESSION_BUS_ADDRESSจะทำให้การแสดงภาพช้าลง
target_PATH="$PATH:$(sudo printenv PATH)";จะเป็นประโยชน์ต่อโดยตรงใช้เส้นทางรากโดยไม่ต้องเพิ่มเติมการแยกวิเคราะห์การส่งออกของหรือenvprintenv
เช่น:
xb@dnxb:~$ sudo env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
xb@dnxb:~$ sudo printenv | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
xb@dnxb:~$ sudo printenv PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
xb@dnxb:~$ sudo env PATH
env: ‘PATH’: No such file or directory
xb@dnxb:~$
มีมุมมองที่แตกต่าง (จาก FreeBSD) คุณมี:
จากman env:
The env utility executes another utility after modifying the environment
as specified on the command line. Each name=value option specifies the
setting of an environment variable, name, with a value of value. All
such environment variables are set before the utility is executed.
...
If no utility is specified, env prints out the names and values of the
variables in the environment, with one name/value pair per line.
จากman printenv:
The printenv utility prints out the names and values of the variables in
the environment, with one name/value pair per line. If name is speci-
fied, only its value is printed.
ดังนั้นคำสั่งเหล่านี้อาจมีผลเหมือนกันโดยไม่มีการโต้แย้ง แต่printenvมีจุดประสงค์เพียงอย่างเดียวคือการแสดงคีย์ / ค่าของสภาพแวดล้อมปัจจุบันในขณะที่envตั้งเป้าหมายเพื่อตั้งค่าสภาพแวดล้อมบางอย่างก่อนที่จะเรียกไบนารี / สคริปต์ / อะไรก็ตาม
ชัดเจนขึ้นด้วยวิธีนี้หรือไม่
รู้จักมากขึ้น:
man 1 env (FreeBSD)man 1 printenv (FreeBSD)env printenvprintenv
env เป็น POSIX 7 ,printenv ไม่ได้ (GNU coreutils ใน Ubuntu 15.10)
จากหน้าคน:
env - รันโปรแกรมในสภาพแวดล้อมที่ถูกปรับเปลี่ยน
...
printenv - พิมพ์ทั้งหมดหรือบางส่วนของสภาพแวดล้อม
ควรอธิบายให้สวย
printenvเพียงพิมพ์ตัวแปรทั้งหมดของสภาพแวดล้อมปัจจุบัน ด้วยenvคุณสามารถเตรียมสภาพแวดล้อมเดียวกันกับการปรับเปลี่ยนบางอย่างถ้าจำเป็นและเรียกใช้แอปในนั้น
lsเป็นไบนารี แต่เป็นนามแฝงร่วมกันซึ่งมักจะเพียงแค่ขยายll และเป็นสองไบนารีที่แตกต่างกันฉันไม่แน่ใจว่าคนแรกที่ได้รับการแนะนำว่า คุณสามารถดูตัวอย่างเพิ่มเติมได้ที่นี่gnu.org/software/coreutils/manual/html_node/env-invocation.htmlls -lprintenvenv
พูดคุยเกี่ยวกับฟังก์ชันการทำงานอย่างเข้มงวดenvเป็นไบนารีที่มีชุดคุณลักษณะขนาดใหญ่หนึ่งในนั้นคือการพิมพ์ตัวแปรสภาพแวดล้อมในขณะที่printenvเพียงพิมพ์ตัวแปรสภาพแวดล้อม
โดยสรุปหากคุณคุ้นเคยกับการทำงานกับ env คุณจะได้ไปกับenvการพิมพ์พวกเขา (เพราะนั่นคือสิ่งที่คุณคุ้นเคย) และหากคุณไม่ได้ใช้คุณจะจำprintenvได้เร็วขึ้น
มีจริงไม่มีความแตกต่างเมื่อพูดถึงprintenvVS envเพียงพิมพ์ตัวแปรสิ่งแวดล้อม ฉันเพิ่งตรวจสอบและ env หนักกว่าเล็กน้อย (ประมาณ 5 KB เพิ่มเติม) และประสิทธิภาพ (ในเวลา) ดูเหมือนว่าจะเหมือนกันทุกประการ
หวังว่านี่จะเป็นการล้างออก! :)
หากคุณต้องการทราบว่าเอาต์พุตของสองไบนารีที่ต่างกันโดยไม่คำนึงถึงประวัติและมรดกของมันนั้นเป็นอย่างไรคุณสามารถรันยูทิลิตี้บางอย่างเพื่อวัดความแตกต่างนี้ เดเบียนฉันวิ่งไปสองสามอย่างที่จะแตกต่างกันไปขึ้นอยู่กับสภาพแวดล้อมที่กำหนดเอง:
env |wc -l
printenv |wc -l
ทั้งเอาต์พุตของฉันมี 41 บรรทัด
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
เอาต์พุต: 41c41 <_ = / usr / bin / env ---
_ = / usr / bin / printenv
ดังนั้นคุณจะเห็นว่ามีหนึ่งบรรทัดที่แตกต่างกันในสองและบรรทัดนั้นคือหมายเลข 41 ซึ่งฉันเดากำหนดไบนารีที่ใช้ในคำสั่ง หากไม่มีข้อโต้แย้งเพิ่มเติมรายงานเหล่านี้จะเป็นข้อมูลเหมือนกันสำหรับฉัน