Answers:
历史上是否有两个命令而不是一个命令的原因?
只是历史的举止。
printenv
在1979年为BSD 编写了第一版Command。env
在1980年引入了命令。env
在1986年跟随UNIX System 。env
在1988年遵循GNU / UNIX系统。printenv
在1988年跟随BSD 。printenv
在1989年跟随MINX / BSD 。printenv
与env
在1991年。请注意,“跟随”并不意味着源代码相同,可能是为了避免许可诉讼而对其进行了重写。
因此,两个命令都存在的原因是,当Bill Joy编写printenv
该时间时,env
尚不存在。经过10年的合并/兼容性和GNU,您现在在同一页面上看到两个相似的命令。
此历史记录表示如下:( 我尝试将答案最小化,因此此处仅提供2个基本源代码,其余的您可以单击附件链接查看)
[1975年秋天]
也是在1975年秋天到达的还有两名未被注意的研究生Bill Joy和Chuck Haley;他们俩都立即对新系统产生了兴趣。最初,他们开始研究汤普森在11/70机房周围闲逛时遭到黑客入侵的Pascal系统。
[1977]
Joy于1978年3月9日开始发行第一个Berkeley软件发行版(1BSD)。// rf:https ://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[1979年2月]
1979(请参阅“ Bill Joy,UCB,1979年2月”)/ 1980(请参阅“ copyright [] =“),printenv.c //rf:http://minnie.tuhs.org/cgi-bin/utree.pl ?文件= 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]
难以确定是在2BSD还是3BSD中发布// //射频: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年6月]
UNIX版本3.0或“ UNIX系统III” // rf:ftp : //pdp11.org.ru/pub/unix-archive/PDP-11/Distributions/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 1st发布// 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
[1988年10月4日]
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
,请参阅[1993年8月12日]。
[1991年7月16日]
“Shellutils” -发布GNU shell编程公用事业1.0 // RF:https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
该软件包中的程序是:
basename日期dirname env expr组id日志名pathchk printenv printf sleep tee tty whoami是不错nohup stty uname
[1993年8月12日]
printenv.c // rf:ftp : //ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/printenv.c
,GNU Shell实用程序1.8 // rf:ftp : //ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/VERSION
/* printenv -- print all or part of environment
Copyright (C) 1989, 1991 Free Software Foundation.
...
[1993]
在2006年在DSLinux源代码上找到的printenv.c // 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
[1993年11月]
FreeBSD的第一个版本已经发布。// RF:https://en.wikipedia.org/wiki/FreeBSD
[2002年9月1日]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
GNU fileutils,textutils和sh-utils(参见1991年7月16日的“ Shellutils”)软件包已合并为一个软件包,称为GNU coreutils。
总体而言,env
用例与printenv
:
printenv
可以做同样的事情enable
cmd 实现。设置变量但没有意义,因为有些外壳已经可以做到了env
,例如
$ HOME = / dev HOME = / tmp USER = root / bin / bash -c“ cd〜; pwd”
/ tmp
#!/usr/bin/env python
标头,但如果env
不在/ usr / bin中,则仍不可移植
env -i
,禁用所有环境。我发现找出某些程序的关键环境变量以使其从运行很有用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)";
直接使用根路径而无需进一步解析env
or 的输出很有用printenv
。
例如:
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
命令出现在4.4BSD中。在FreeBSD 6.0中增加了-P,-S和-v选项。 该printenv
命令出现在3.0BSD中。因此,历史原因似乎是printenv
首先到达的。
从手册页:
env-在修改后的环境中运行程序
...
printenv-打印全部或部分环境
应该很好解释。
printenv
只是打印当前环境的所有变量。有了env
你可以准备与必要时一些修改同一个环境中,并在其中运行的应用程序。
ls
是二进制文件,但是ll
常用别名,通常会扩展为ls -l
。printenv
并且env
是两种不同的二进制文件,但我不确定首先介绍哪种二进制文件。你可以在这里看到更多的例子gnu.org/software/coreutils/manual/html_node/env-invocation.html
严格地讲功能,env
是具有大量功能的二进制文件,其中之一是打印环境变量,而printenv
仅打印环境变量。
总结一下,如果您习惯使用env,则将使用env
它们进行打印(因为这是您惯用的方法),如果您不习惯,则通常会记得printenv
更快。
printenv
与env
仅打印环境变量相比,谈论实际上几乎没有区别。我刚刚检查了一下,env稍重(大约多了5 KB),并且它们的性能(及时)似乎完全相同。
希望这可以解决!:)
如果您真的想知道这两个二进制文件的历史记录和历史记录如何,那么它们的输出有何不同,可以运行一些实用程序来评估这种差异。在debian上,我运行了一些内容,具体取决于任何自定义环境var:
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,我想这是命令中使用的二进制代码。在没有其他参数的情况下,这些为我报告了虚拟的相同信息。