Яка різниця між "env" та "printenv"?


67

Яка різниця між двома командами envта printenv? Вони обидва показують змінні середовища, і вихід точно такий же, як і від _.

Чи є історичні причини того, що замість однієї є дві команди?

Відповіді:


49

Чи є історичні причини того, що замість однієї є дві команди?

Існувала просто манера історії.

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

Зауважте, що "слідував" не означає, що вихідний код був однаковим, ймовірно, вони були переписані, щоб уникнути позовів про ліцензію.

Тож причина, чому обидві команди існували, полягає в тому, що коли Білл Джой писав printenvтой час, її envще не існує. Після 10 років злиття / сумісності та GNU натрапив на нього, ви зараз бачите обидві подібні команди на одній сторінці.

Ця історія вказується так: (Я намагаюся мінімізувати відповідь, і так надається тут лише 2 основних вихідних коду, решта ви можете натиснути додані посилання, щоб побачити)

[осінь 1975]

Також восени 1975 року прибули двоє непомічених аспірантів, Білл Джой та Чак Хейлі; вони обоє негайно зацікавились новою системою. Спочатку вони почали працювати над системою Паскаля, яку Томпсон зламав разом, розвішуючи машинну кімнату 11/70.

[1977]

Радість почала складати перший дистрибутив програмного забезпечення Берклі (1BSD), який вийшов 9 березня 1978 року. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Лютий, 1979]

1979 р. (Див. "Білл Радість, УКБ лютого 1979 р.") / 1980 р. (Див. "Авторське право [] ="), 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

[Червень 1980 р.]

Випуск UNIX 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 1-го випуску // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum написав клон UNIX під назвою MINIX (MINi-unIX) для комп'ютера IBM. Він був орієнтований на студентів та інших, хто хотів дізнатися, як працює операційна система.

[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 // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

Програми цього пакету:

базове ім'я dirname env expr групи id ім'я ім'я pathchk printenv printf сон tee tty whoami так добре nohup stty unme

[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 (див. "Shellutils" 16 липня 1991 року вище) пакети були об'єднані в один, який називається coreutils GNU.

Загалом, 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
Приємний урок історії.
Оукі

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його встановити деяке середовище перед тим, як викликати інший бінарний / скрипт / будь-який інший.

Чи більш зрозуміло це?

Щоб знати більше:


2
З наданих посилань: команда з'явилася в 4.4BSD. Параметри -P, -S та -v були додані у FreeBSD 6.0. Команда з'явилася в 3.0BSD. Тож історична причина, здається, була такою, яка прибула першою. env printenvprintenv
mcmlxxxvi


3

З довідкових сторінок:

env - запуск програми в модифікованому середовищі

...

printenv - друкує все або частину середовища

Повинно бути досить пояснювальним.


4
але я не розумію ...
mikeserv

Я припускаю, що env перед принтеном. То навіщо робити ще один бінарний? Це не те саме, що 'll' до 'ls', оскільки 'll' не є двійковим і не має довідної сторінки.
WiSaGaN

@mikeserv printenvпросто друкує всі змінні поточного середовища. З envви можете приготувати в ту ж середу з деякими змінами , в разі необхідності і запустити додаток в ньому.
УВВ

@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швидше.

Практично немає відмінностей, якщо говорити про printenvvs 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 / bin / printenv

Таким чином, ви бачите, що у двох є один рядок, і цей рядок є номером 41, який, напевно, визначає двійковий код, який використовується в команді. Без додаткових аргументів ці звіти повідомляють віртуальну ідентичну для мене інформацію.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.