Ответы:
Существуют ли какие-либо исторические причины существования двух команд вместо одной?
Была только историческая манера.
printenv
команды в 1979 году для BSD.env
команду в 1980 году.env
в 1986 году.env
в 1988 году.printenv
в 1988 году.printenv
в 1989 году.printenv
и env
в 1991 году.Обратите внимание, что слово "follow" не означает, что исходный код был таким же, вероятно, они были переписаны, чтобы избежать судебного иска.
Таким образом, причина существования обеих команд заключается в том, что когда Билл Джой написал printenv
это время, его env
еще не было. После 10 лет слияния / совместимости и GNU с этим столкнулись, теперь вы видите обе подобные команды на одной странице.
Эта история обозначается следующим образом: (Я стараюсь свести к минимуму ответ и поэтому здесь представлен только 2 основных исходных кода, остальные вы можете нажать на прикрепленные ссылки, чтобы увидеть)
[осень 1975 года]
Осенью 1975 года также прибыли двое незаметных аспирантов, Билл Джой и Чак Хейли; они оба сразу заинтересовались новой системой. Первоначально они начали работать над системой Pascal, которую Томпсон взломал вместе, пока висел в машинном зале 11/70.
[1977]
Джой начал собирать первый дистрибутив программного обеспечения Berkeley (1BSD), который был выпущен 9 марта 1978 года. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Февраль 1979 года]
1979 (см. «Bill Joy, UCB February, 1979») / 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 // 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 Release 3.0 ИЛИ «UNIX System 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 для печати // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1, но я не могу найти руководство, связанное с env наиболее близким является getenv и окружающая среда // 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 октября 1988]
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
Программы в этом пакете:
базовое имя дата dirname env expr группы id логин pathchk printenv printf sleep tee tty whoami да хороший nohup stty uname
[12 августа 1993 г.]
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/VERSION
/* printenv -- print all or part of environment
Copyright (C) 1989, 1991 Free Software Foundation.
...
[1993]
printenv.c, найденный в исходном коде DSLinux в 2006 году // 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
Пакеты GNU fileutils, textutils и sh-utils (см. «Shellutils» от 16 июля 1991 г. выше) были объединены в один, называемый 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
, отключить все 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)";
Полезно использовать прямой путь к корню без необходимости дальнейшего анализа выходных данных env
или 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. Опции -P, -S и -v были добавлены в FreeBSD 6.0. Команда printenv
появилась в 3.0BSD. Таким образом, историческая причина, кажется, в том, что printenv
пришла первой.
env
это POSIX 7 ,printenv
это не так (GNU Coreutils в Ubuntu 15.10).
С man-страниц:
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 лишних КБ), и их производительность (во времени) кажется точно такой же.
Надеюсь, это все прояснит! :)
Если вы действительно хотите знать, как различаются выходные данные двух двоичных файлов, независимо от их истории и наследства, вы можете запустить несколько утилит, чтобы измерить эту разницу. На Debian я запустил несколько вещей, которые будут отличаться в зависимости от любых пользовательских переменных среды:
env |wc -l
printenv |wc -l
Оба моих выхода имеют 41 строку
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Выход: 41c41 <_ = / usr / bin / env ---
_ = / USR / бен / printenv
Итак, вы видите, что есть одна строка, отличающаяся от двух, и эта строка имеет номер 41, который, я думаю, определяет двоичный файл, используемый в команде. Без дополнительных аргументов, они сообщают мне практически идентичную информацию.