В чем разница между «env» и «printenv»?

67

В чем разница между двумя командами envи printenv? Они оба показывают переменные окружения, и выходные данные точно такие же, кроме _.

Существуют ли какие-либо исторические причины существования двух команд вместо одной?

WiSaGaN
источник

Ответы:

49

Существуют ли какие-либо исторические причины существования двух команд вместо одной?

Была только историческая манера.

  1. Билл Джой написал первую версию printenvкоманды в 1979 году для BSD.
  2. UNIX System III ввела envкоманду в 1980 году.
  3. GNU последовал за системой UNIX envв 1986 году.
  4. BSD последовал за системой GNU / UNIX envв 1988 году.
  5. MINIX последовал за BSD printenvв 1988 году.
  6. GNU последовал за MINX / BSD printenvв 1989 году.
  7. Утилиты программирования оболочки GNU 1.0 включены printenvи envв 1991 году.
  8. Утилиты GNU Shell объединились с GNU coreutils в 2002 году, и это то, что вы легко могли найти в настоящее время в GNU / Linux.

Обратите внимание, что слово "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

[Июнь 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

  • Таненбаум написал клон UNIX под названием MINIX (MINi-unIX) для IBM PC. Он был нацелен на студентов и других, кто хотел узнать, как работает операционная система.

[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:

  1. вывести переменные окружения, но printenvможно сделать то же самое
  2. Отключить встроенную оболочку, но можно и с помощью enablecmd.
  3. установить переменную, но бессмысленно, потому что некоторые оболочки уже могут делать это env, например,

    $ HOME = / dev HOME = / tmp USER = root / bin / bash -c "cd ~; pwd"

    / TMP

  4. #!/usr/bin/env pythonзаголовок, но все еще не переносимый, если envне в / usr / bin

  5. 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заставит замедлить отображение изображения.

  6. 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:~$
林果 皞
источник
4
Хороший урок истории.
Ouki
21

Имея другую точку зрения (из 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ставя целью установить некоторое окружение перед вызовом другого двоичного файла / сценария / чего угодно.

Разве так понятнее?

Чтобы узнать больше:

Ouki
источник
2
Из приведенных ссылок: Команда envпоявилась в 4.4BSD. Опции -P, -S и -v были добавлены в FreeBSD 6.0. Команда printenvпоявилась в 3.0BSD. Таким образом, историческая причина, кажется, в том, что printenvпришла первой.
mcmlxxxvi
3

С man-страниц:

env - запустить программу в измененной среде

...

printenv - печатать все или часть окружения

Должно быть довольно объяснительным.

УВВ
источник
4
но я не понимаю ...
mikeserv
Я полагаю, что env предшествует printenv. Так зачем делать еще один бинарный файл? Это не то же самое, что «ll» для «ls», так как «ll» не является двоичным файлом и не имеет man-страницы.
WiSaGaN
@mikeserv printenvпросто печатает все переменные текущей среды. С envего помощью можно подготовить ту же среду с некоторыми изменениями, если необходимо, и запустить приложение в ней.
UVV
@ WiSaGaN ваше сравнение не совсем верно. lsэто двоичный файл, но llэто общий псевдоним, который обычно просто расширяется до ls -l. printenvи envэто два разных двоичных файла, но я не уверен, какой из них был представлен первым. Вы можете увидеть еще несколько примеров здесь gnu.org/software/coreutils/manual/html_node/env-invocation.html
UVV
1
@mikeserv, см. текст при наведении мыши на этот комикс . :)
Wildcard
3

Говоря строго о функциональности, envэто двоичный файл с огромным набором функций, одна из которых - печать переменных среды, тогда как printenvпросто печатает переменные среды.

Подводя итог, если вы привыкли работать с env, вы будете envпечатать их (потому что это то, к чему вы привыкли), а если нет, вы, как правило, будете помнить printenvбыстрее.

Там практически нет разницы , когда речь идет о printenvпротив envтолько за печать переменных окружения. Я только что проверил, и env немного тяжелее (около 5 лишних КБ), и их производительность (во времени) кажется точно такой же.

Надеюсь, это все прояснит! :)

Давид Гонсалес Руис
источник
-1

Если вы действительно хотите знать, как различаются выходные данные двух двоичных файлов, независимо от их истории и наследства, вы можете запустить несколько утилит, чтобы измерить эту разницу. На 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, который, я думаю, определяет двоичный файл, используемый в команде. Без дополнительных аргументов, они сообщают мне практически идентичную информацию.

охотник
источник