Jaka jest różnica między „env” a „printenv”?

67

Jaka jest różnica między tymi dwoma poleceniami envi printenv? Oba pokazują zmienne środowiskowe, a wynik jest dokładnie taki sam _.

Czy są jakieś historyczne powody, dla których istnieją dwa polecenia zamiast jednego?

WiSaGaN
źródło

Odpowiedzi:

49

Czy są jakieś historyczne powody, dla których istnieją dwa polecenia zamiast jednego?

Był tylko sposób historyczny.

  1. Bill Joy napisał pierwszą wersję printenvpolecenia w 1979 r. Dla BSD.
  2. UNIX System III wprowadził envpolecenie w 1980 roku.
  3. GNU podążył za systemem UNIX envw 1986 roku.
  4. BSD podążyło za systemem GNU / UNIX envw 1988 roku.
  5. MINIX podążył za BSD printenvw 1988 roku.
  6. GNU podążył za MINX / BSD printenvw 1989 roku.
  7. Dołączone narzędzia do programowania powłoki GNU 1.0 printenvoraz envw 1991 roku.
  8. GNU Shell Utilities połączyło się w jądra GNU w 2002 roku, co w dzisiejszych czasach można łatwo znaleźć w GNU / Linux.

Zauważ, że „obserwowane” nie oznacza, że ​​kod źródłowy był taki sam, prawdopodobnie zostały przepisane w celu uniknięcia procesu licencyjnego.

Powodem, dla którego istniały oba polecenia, jest to, że kiedy Bill Joy napisał printenvten czas, envjeszcze nie istnieje. Po 10 latach scalania / kompatybilności i GNU natrafisz na to, teraz widzisz oba podobne polecenia na tej samej stronie.

Historia ta wskazuje, co następuje: (Staram się zminimalizować odpowiedź, dlatego podaje tylko 2 niezbędne kody źródłowe, resztę możesz kliknąć w załączone linki, aby zobaczyć)

[jesień 1975]

Jesienią 1975 r. Przybyli także dwaj niezauważeni absolwenci, Bill Joy i Chuck Haley; oboje natychmiast zainteresowali się nowym systemem. Początkowo rozpoczęli pracę nad systemem Pascal, który Thompson zhakował razem, kręcąc się po maszynowni 11/70.

[1977]

Joy zaczął kompilować pierwszą Berkeley Software Distribution (1BSD), która została wydana 9 marca 1978 r. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Luty 1979]

1979 (patrz „Bill Joy, UCB luty 1979”) / 1980 (patrz „copyright [] =”), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? plik = 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]

Trudno ustalić, wydany w 2BSD LUB 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Czerwiec 1980]

UNIX Release 3.0 LUB „UNIX System III” // rf: ftp://pdp11.org.ru/pub/unix-archive/PDP-11/Distribution/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 pierwsza instrukcja printenv // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1, ale nie mogę znaleźć instrukcji związanej z env , najbliższy jest getenv i environment // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man

[1986]

Pierwsza wersja GNU env// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/env.c

[1987]

Wydano MINIX 1st // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum napisał klon systemu UNIX o nazwie MINIX (MINi-unIX) na komputer IBM. Był skierowany do studentów i innych osób, które chciały dowiedzieć się, jak działa system operacyjny.

[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 października 1988 r.]

Wersja MINIX 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI

... 32932 190 /minix/commands/printenv.c //printenv.c już istnieje

// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm

[1989]

Pierwsza wersja GNU printenv, patrz [12 sierpnia 1993].

[16 lipca 1991 r.]

„Shellutils” - udostępniono narzędzia do programowania powłoki GNU 1.0 // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

Programy w tym pakiecie to:

data basename dirname env grupy expr id LOGNAME pathchk printenv printf sen tee tty whoami tak miły nohup stty uname

[12 sierpnia 1993 r.]

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, który znalazł w kodzie źródłowym DSLinux w 2006 r. // rf: pamięć podręczna (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

[Listopad 1993]

Pierwsza wersja FreeBSD została wydana. // rf: https://en.wikipedia.org/wiki/FreeBSD

[1 września 2002 r.]

http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils

Paczki plików GNU, textutils i sh-utils (patrz „Shellutils” 16 lipca 1991 r. Powyżej) zostały połączone w jeden, zwany coreutils GNU.

Ogólnie envprzypadki użycia porównują z printenv:

  1. wypisuje zmienne środowiskowe, ale printenvmoże zrobić to samo
  2. Wyłącz wbudowaną powłokę, ale można to również osiągnąć za pomocą enablecmd.
  3. ustaw zmienną, ale bez sensu, ponieważ niektóre powłoki już mogą to zrobić bez env, np

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

    / tmp

  4. #!/usr/bin/env pythonnagłówek, ale nadal nie jest przenośny, jeśli envnie znajduje się w / usr / bin

  5. env -i, wyłącz wszystkie środowiska. Uznałem, że przydatne jest ustalenie krytycznych zmiennych środowiskowych dla niektórych programów, z których można je uruchomić crontab. np. [1] W trybie interaktywnym uruchom, declare -p > /tmp/d.shaby zapisać zmienne atrybutów. [2] W /tmp/test.sh, napisz: . /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg[3] Teraz uruchom env -i bash /tmp/test.sh[4] Jeśli wyświetlanie obrazu się powiedzie, usuń połowę zmiennych /tmp/d.shi uruchom env -i bash /tmp/test.shponownie. Jeśli coś się nie powiedzie, cofnij to. Powtórz krok w celu zawężenia. [5] Wreszcie stwierdziłem, że eogwymaga $DISPLAYwbiegania crontab, a nieobecność $DBUS_SESSION_BUS_ADDRESSspowolni wyświetlanie obrazu.

  6. target_PATH="$PATH:$(sudo printenv PATH)";jest użyteczny do bezpośredniego użycia ścieżki katalogu głównego bez konieczności dalszego analizowania danych wyjściowych envlub printenv.

na przykład:

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:~$
林果 皞
źródło
4
Ładna lekcja historii.
Ouki,
21

Mając inny punkt widzenia (z FreeBSD), masz:

Od 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.

Od 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.

Więc te polecenia mogą mieć ten sam efekt bez argumentów, ale printenvjedynym celem jest wyświetlenie bieżącego klucza / wartości środowiska, a envcelem jest ustawienie jakiegoś środowiska przed wywołaniem innego pliku binarnego / skryptu / cokolwiek.

Czy w ten sposób jest to bardziej jasne?

Aby wiedzieć więcej:

Ouki
źródło
2
Z dostarczonych linków: Komenda pojawiła się w 4.4BSD. Opcje -P, -S i -v zostały dodane w FreeBSD 6.0. Komenda pojawiła się w 3.0BSD. Wydaje się, że przyczyną historyczną był pierwszy. env printenvprintenv
mcmlxxxvi,
3

Ze stron podręcznika:

env - uruchom program w zmodyfikowanym środowisku

...

printenv - wydrukuj całość lub część środowiska

Powinno być dość objaśniające.

UVV
źródło
4
ale nie rozumiem ...
Mikeserv
Przypuszczam, że env jest przed printenv. Po co więc tworzyć kolejne pliki binarne? To nie jest to samo z tym, co „ll” na „ls”, ponieważ „ll” nie jest plikiem binarnym i nie ma strony podręcznika.
WiSaGaN
@mikeserv printenvpo prostu drukuje wszystkie zmienne bieżącego środowiska. Dzięki envmożesz przygotować to samo środowisko z pewnymi modyfikacjami, jeśli to konieczne, i uruchomić w nim aplikację.
UVV
@WiSaGaN twoje porównanie nie jest naprawdę poprawne. lsjest plikiem binarnym, ale lljest popularnym aliasem, który zwykle po prostu się rozwija ls -l. printenvi envsą to dwa różne pliki binarne, nie jestem jednak pewien, który został wprowadzony jako pierwszy. Możesz zobaczyć więcej przykładów tutaj gnu.org/software/coreutils/manual/html_node/env-invocation.html
UVV
1
@ Mikeserv, zobacz tekst najechania kursorem myszy na ten komiks . :)
Wildcard,
3

Mówiąc ściśle o funkcjonalnościach, envjest to plik binarny z ogromnym zestawem funkcji, jedną z nich jest drukowanie zmiennych środowiskowych, podczas gdy printenvtylko drukowanie zmiennych środowiskowych.

Podsumowując, jeśli jesteś przyzwyczajony do pracy z env, pójdziesz z envdrukowaniem ich (ponieważ do tego jesteś przyzwyczajony), a jeśli nie, zazwyczaj będziesz pamiętać printenvszybciej.

Nie ma praktycznie żadnych różnic, gdy mówimy o printenvvs envtylko do drukowania zmiennych środowiskowych. Właśnie sprawdziłem, a env jest nieco cięższy (około 5 dodatkowych KB), a ich wydajność (w czasie) wydaje się dokładnie taka sama.

Mam nadzieję, że to wyjaśni! :)

David González Ruiz
źródło
-1

Jeśli naprawdę chcesz wiedzieć, jak różne są dane wyjściowe dwóch plików binarnych, bez względu na ich historię i dziedzictwo, możesz uruchomić kilka narzędzi, aby ocenić tę różnicę. Na Debianie uruchomiłem kilka rzeczy, które będą się różnić w zależności od niestandardowych zmiennych środowiskowych:

env |wc -l
printenv |wc -l

Oba moje wyjście ma 41 linii

env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt

Wyjście: 41c41 <_ = / usr / bin / env ---

_ = / usr / bin / printenv

Widzicie więc, że w obu jest jedna linia inna i ta linia ma numer 41, co, jak sądzę, określa plik binarny użyty w poleceniu. Bez dodatkowych argumentów raportują one dla mnie wirtualne identyczne informacje.

myśliwy
źródło