env
和两个命令有什么区别printenv
?它们都显示环境变量,并且输出除了 之外完全相同_
。
有两个命令而不是一个命令有什么历史原因吗?
答案1
有两个命令而不是一个命令有什么历史原因吗?
这就是历史的方式。
历史
printenv
Bill Joy于 1979 年为 BSD编写了命令的第一个版本。- UNIX System III
env
于 1980 年引入了命令。 - GNU 于 1986 年继 UNIX 系统之后出现
env
。 - BSD 于 1988 年继 GNU/UNIX 系统之后出现
env
。 - MINIX 于 1988 年紧随 BSD 的脚步
printenv
。 - GNU 于 1989 年跟随 MINX/BSD 的脚步
printenv
。 - 1991 年
printenv
包含GNU shell 编程实用程序 1.0 。env
- GNU Shell Utilities 于 2002 年合并到 GNU coreutils,这就是您现在在 GNU/Linux 中看到的。
请注意,“遵循”并不意味着源代码是相同的,可能它们被重写以避免许可诉讼。
因此,这两个命令之所以存在,是因为 Bill Joy在存在printenv
之前就已经写过env
。经过 10 年的合并/兼容性和 GNU 遇到它之后,您现在可以在同一页面上看到两个相似的命令。
这段历史表明: (我试图尽量减少答案,只在这里提供了两个基本的源代码片段。其余的你可以点击附加的链接查看更多)
[1975年秋天]
1975 年秋天,还有两名未被注意到的研究生比尔·乔伊 (Bill Joy) 和查克·黑利 (Chuck Haley) 也来到了这里。他们都立即对新系统产生了兴趣。最初,他们开始研究汤普森在 11/70 机房闲逛时一起破解的 Pascal 系统。
[1977]
Joy 开始编译第一个 Berkeley Software Distribution (1BSD),并于 1978 年 3 月 9 日发布。 //rf:https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[1979 年 2 月]
1979 年(参见“Bill Joy,UCB 二月,1979 年”)/1980 年(参见“copyright[] ="),printenv.c //rf:http://minnie.tuhs.org/cgi-bin/utree.pl?file=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 中发布的 //rf:https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD printenv 命令出现在 3.0 BSD 中。 //射频:http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 1979 年推出的 3.0 BSD //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
- Tanenbaum 为 IBM PC 编写了 UNIX 的克隆版本,称为 MINIX (MINI-unIX)。它针对的是学生和其他想要了解操作系统如何工作的人。
[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 已经存在
//射频: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
该软件包中的程序有:
基本名称 日期 目录名环境expr 组 id 日志名 路径chk打印环境 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]
printenv.c 于 2006 年在 DSLinux 源代码中找到 //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 的第一个版本发布。 //射频: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
可以做同样的事情禁用 shell 内置功能,但
enable
也可以使用 cmd 实现。设置变量但毫无意义,因为某些 shell 已经可以在没有 的情况下完成它
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:~$
答案2
拥有不同的观点(来自 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
(自由BSD)man 1 printenv
(自由BSD)
答案3
答案4
严格来说,env
它是一个具有大量功能的二进制文件,其中之一是打印环境变量,而printenv
只是打印环境变量。
总而言之,如果您习惯使用 env,您将继续env
打印它们(因为这就是您习惯的),如果您不习惯,您通常会记住得printenv
更快。
谈论printenv
环境变量env
与仅打印环境变量实际上没有区别。我刚刚检查了一下,env 稍微重一些(大约多了 5 KB),并且它们的性能(及时)似乎完全相同。
希望这能解决问题! :)