Câu trả lời:
Có bất kỳ lý do lịch sử cho việc có hai lệnh thay vì một?
Có cách lịch sử.
printenv
lệnh vào năm 1979 cho BSD.env
lệnh vào năm 1980.env
vào năm 1986.env
vào năm 1988.printenv
năm 1988.printenv
vào năm 1989.printenv
và env
vào năm 1991.Lưu ý rằng "theo sau" không có nghĩa là mã nguồn giống nhau, có thể chúng được viết lại để tránh kiện cáo giấy phép.
Vì vậy, lý do tại sao cả hai lệnh tồn tại là vì khi Bill Joy viết printenv
vào thời điểm đó, env
nó vẫn chưa tồn tại. Sau 10 năm hợp nhất / tương thích và GNU đi qua nó, bây giờ bạn đang thấy cả hai lệnh tương tự trên cùng một trang.
Lịch sử này được chỉ ra như sau: (Tôi cố gắng thu nhỏ câu trả lời và do đó chỉ cung cấp 2 mã nguồn thiết yếu ở đây, phần còn lại bạn có thể nhấp vào các liên kết đính kèm để xem)
[mùa thu năm 1975]
Cũng đến mùa thu năm 1975 là hai sinh viên tốt nghiệp không được chú ý là Bill Joy và Chuck Haley; cả hai đều quan tâm ngay lập tức đến hệ thống mới. Ban đầu, họ bắt đầu làm việc trên một hệ thống Pascal mà Thompson đã hack cùng nhau trong khi treo xung quanh phòng máy 11/70.
[1977]
Joy bắt đầu biên dịch Bản phân phối phần mềm Berkeley (1BSD) đầu tiên, được phát hành vào ngày 9 tháng 3 năm 1978. // rf: https://en.wikipedia.org/wiki/Ber siêu_Software_Distribution
[Tháng Hai, 1979]
1979 (xem "Bill Joy, UCB tháng 2 năm 1979") / 1980 (xem "bản quyền [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? tệp = 2.11BSD / src / ucb / 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]
Khó xác định được phát hành trong 2BSD HOẶC 3BSD // rf: https://en.wikipedia.org/wiki/Ber siêu_Software_Distribution
3BSD Lệnh printenv xuất hiện trong 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD được giới thiệu vào năm 1979 // rf: http://gunkies.org/wiki/3_BSD
2BSD Lệnh printenv xuất hiện lần đầu tiên trong 2BSD // rf: http://man.openbsd.org/printenv.1
[Tháng Sáu, 1980]
UNIX Release 3.0 HOẶC "Hệ thống UNIX 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]
Hướng dẫn sử dụng printenv đầu tiên của BSD // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 nhưng tôi không thể tìm thấy hướng dẫn liên quan đến env , gần nhất là getenv và môi trường // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Phiên bản đầu tiên của GNU env
// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-release/i386/1.0-RELEASE/ports/shellutils/src/env.c
[1987]
MINIX đầu tiên được phát hành // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum
[1988]
Bv 1 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 tháng 10 năm 1988]
Phiên bản MINIX 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c đã tồn tại
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Phiên bản đầu tiên của GNU printenv
, tham khảo [12 tháng 8 năm 1993].
[16 tháng 7 năm 1991]
"Shellutils" - Các tiện ích lập trình shell GNU 1.0 được phát hành // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Các chương trình trong gói này là:
tên cơ sở ngày dirname env expr nhóm id logname pathchk printenv printf ngủ tee tty whoami yes đẹp nohup stty uname
[12 tháng 8 năm 1993]
printenv.c // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-release/i386/1.0-RELEASE/ports/shellutils/src/printenv.c
, GNU Shell Utility 1.8 // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-release/i386/1.0-RELEASE/ports/shellutils/VERSION
/* printenv -- print all or part of environment
Copyright (C) 1989, 1991 Free Software Foundation.
...
[1993]
printenv.c được tìm thấy trên mã nguồn DSLinux năm 2006 // rf: (Google) cache: 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
[Tháng 11 năm 1993]
Phiên bản đầu tiên của FreeBSD đã được phát hành. // rf: https://en.wikipedia.org/wiki/FreeBSD
[tháng 1 năm 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
Các tập tin GNU, textutils và sh-utils (xem "Shellutils" vào ngày 16 tháng 7 năm 1991 ở trên) đã được hợp nhất thành một, được gọi là các lõi GNU.
Nhìn chung, env
các trường hợp sử dụng so với printenv
:
printenv
có thể làm tương tựenable
cmd.thiết lập biến nhưng vô nghĩa do một số shell đã có thể làm điều đó mà không có env
, ví dụ
$ HOME = / dev HOME = / tmp NGƯỜI DÙNG = root / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env python
tiêu đề, nhưng vẫn không thể di động nếu env
không trong / usr / bin
env -i
, vô hiệu hóa tất cả env. Tôi thấy nó hữu ích để tìm ra các biến môi trường quan trọng cho chương trình nhất định để làm cho nó chạy từ đó crontab
. ví dụ [1] Trong chế độ tương tác, chạy declare -p > /tmp/d.sh
để lưu trữ các biến thuộc tính. [2] In /tmp/test.sh
, write: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg
[3] Bây giờ chạy env -i bash /tmp/test.sh
[4] Nếu thành công để hiển thị hình ảnh, hãy loại bỏ một nửa biến trong /tmp/d.sh
và chạy env -i bash /tmp/test.sh
lại. Nếu một cái gì đó thất bại, hoàn tác nó. Lặp lại bước để thu hẹp. [5] Cuối cùng tôi nhận ra eog
cần $DISPLAY
phải chạy vào crontab
, và vắng mặt $DBUS_SESSION_BUS_ADDRESS
sẽ làm chậm việc hiển thị hình ảnh.
target_PATH="$PATH:$(sudo printenv PATH)";
là hữu ích để sử dụng trực tiếp đường dẫn gốc mà không cần phải phân tích cú pháp đầu ra của env
hoặc printenv
.
ví dụ:
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:~$
Có quan điểm khác (từ FreeBSD), bạn có:
Từ 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.
Từ 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.
Vì vậy, các lệnh này có thể có tác dụng tương tự mà không cần đối số, nhưng printenv
mục đích duy nhất là hiển thị khóa / giá trị môi trường hiện tại trong khi env
mục tiêu là đặt một số môi trường trước khi gọi một nhị phân / script / bất cứ thứ gì.
Có phải rõ ràng hơn theo cách này?
Để biết thêm:
man 1 env
(FreeBSD)man 1 printenv
(FreeBSD)env
lệnh xuất hiện trong 4.4BSD. Các tùy chọn -P, -S và -v đã được thêm vào FreeBSD 6.0. Các printenv
lệnh xuất hiện trong 3.0BSD. Vì vậy, lý do lịch sử dường như là printenv
đến đầu tiên.
env
là POSIX 7 ,printenv
không phải (GNU Coreutils trong Ubuntu 15.10).
Từ trang con người:
env - chạy chương trình trong môi trường đã sửa đổi
...
printenv - in tất cả hoặc một phần của môi trường
Nên được giải thích khá.
printenv
chỉ in tất cả các biến của môi trường hiện tại. Với env
bạn có thể chuẩn bị môi trường tương tự với một số sửa đổi nếu cần thiết và chạy một ứng dụng trong đó.
ls
là một nhị phân, nhưng ll
là một bí danh phổ biến, thường chỉ mở rộng ra ls -l
. printenv
và env
là hai nhị phân khác nhau, tôi không chắc cái nào được giới thiệu trước. Bạn có thể xem thêm một số ví dụ tại đây gnu.org/software/coreutils/manual/html_node/env-invocation.html
Nói một cách nghiêm túc về các chức năng, env
là một hệ nhị phân với một bộ tính năng khổng lồ, một trong số đó là in các biến môi trường, trong khi printenv
chỉ in các biến môi trường.
Tóm tắt, nếu bạn đã quen làm việc với env, bạn sẽ đi cùng env
để in chúng (vì đó là những gì bạn đã quen) và nếu bạn không, bạn thường sẽ nhớ printenv
nhanh hơn.
Thực tế không có sự khác biệt khi nói về printenv
vs env
chỉ in các biến môi trường. Tôi mới kiểm tra và env nặng hơn một chút (khoảng 5 KB thêm) và hiệu suất của chúng (theo thời gian) dường như giống hệt nhau.
Hy vọng điều này sẽ xóa nó ra! :)
Nếu bạn thực sự muốn biết đầu ra của hai nhị phân khác nhau như thế nào bất kể lịch sử và di sản của chúng, bạn có thể chạy một vài tiện ích để đánh giá sự khác biệt này. Trên debian tôi đã chạy một vài thứ sẽ khác nhau tùy thuộc vào bất kỳ lọ môi trường tùy chỉnh nào:
env |wc -l
printenv |wc -l
Cả hai đầu ra của tôi có 41 dòng
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Đầu ra: 41c41 <_ = / usr / bin / env ---
_ = / usr / bin / printenv
Vì vậy, bạn thấy có một dòng khác nhau trong hai và dòng đó là số 41 mà tôi đoán quy định nhị phân được sử dụng trong lệnh. Không có đối số bổ sung, những báo cáo thông tin giống hệt ảo cho tôi.