Was ist der Unterschied zwischen "env" und "printenv"?

67

Was ist der Unterschied zwischen den beiden Befehlen envund printenv? Beide zeigen die Umgebungsvariablen und die Ausgabe ist bis auf genau die gleiche _.

Gibt es historische Gründe dafür, dass es zwei anstelle von einem Befehl gibt?

WiSaGaN
quelle

Antworten:

49

Gibt es historische Gründe dafür, dass es zwei anstelle von einem Befehl gibt?

Es gab nur Geschichte.

  1. Bill Joy schrieb printenv1979 die erste Version des Befehls für BSD.
  2. UNIX System III führte den envBefehl 1980 ein.
  3. GNU folgte env1986 den UNIX-Systemen .
  4. BSD folgte env1988 GNU / UNIX-Systemen .
  5. MINIX folgte printenv1988 BSD .
  6. GNU folgte MINX / BSD printenvim Jahr 1989.
  7. GNU Shell Programming Utilities 1.0 enthalten printenvund envim Jahr 1991.
  8. GNU Shell Utilities wurden im Jahr 2002 zu GNU coreutils zusammengeführt, was heutzutage in GNU / Linux leicht zu finden war.

Beachten Sie, dass "gefolgt" nicht bedeutet, dass der Quellcode derselbe ist. Wahrscheinlich wurden sie umgeschrieben, um Lizenzstreitigkeiten zu vermeiden.

Der Grund, warum beide Befehle existierten, ist, printenvdass sie envnoch nicht existierten, als Bill Joy diese Zeit schrieb . Nach 10 Jahren Merging / Compatibility und GNU sehen Sie nun beide ähnlichen Befehle auf derselben Seite.

Dieser Verlauf zeigt Folgendes an: (Ich versuche, die Antwort zu minimieren und biete hier nur zwei wichtige Quellcodes an. Den Rest können Sie durch Klicken auf die angehängten Links sehen.)

[Herbst 1975]

Ebenfalls im Herbst 1975 trafen zwei unbemerkte Doktoranden ein, Bill Joy und Chuck Haley; Beide interessierten sich sofort für das neue System. Zunächst arbeiteten sie an einem Pascal-System, das Thompson zusammen gehackt hatte, als er im Maschinenraum 11/70 herumlungerte.

[1977]

Joy begann die erste Berkeley Software Distribution (1BSD) kompilieren, die am 9. März veröffentlicht wurde, 1978 // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Februar 1979]

1979 (siehe "Bill Joy, UCB February 1979") / 1980 (siehe "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]

Schwer zu bestimmen, veröffentlicht in 2BSD ODER 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Juni 1980]

UNIX Release 3.0 ODER "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-Handbuch für den ersten Druck // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1, aber ich kann kein Handbuch zu env finden Am nächsten ist getenv und environ // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man

[1986]

Erste Version von 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 veröffentlicht // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum hat einen UNIX-Klon namens MINIX (MINi-unIX) für den IBM-PC geschrieben. Es richtete sich an Studenten und andere, die lernen wollten, wie ein Betriebssystem funktioniert.

[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. Oktober 1988]

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

... 32932 190 /minix/commands/printenv.c //printenv.c existiert bereits

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

[1989]

Erste Version von GNU printenv, siehe [12. August 1993].

[16. Juli 1991]

"Shellutils" - GNU Shell Programming Utilities 1.0 veröffentlicht // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

Die Programme in diesem Paket sind:

basename date dirname env expr gruppen id logname pathchk printenv printf sleep tty whoami yes nice nohup stty uname

[12. August 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, das 2006 im DSLinux-Quellcode gefunden wurde. html

--- NEW FILE: printenv.c ---
/*
 * Copyright (c) 1993 by David I. Bell

[November 1993]

Die erste Version von FreeBSD wurde veröffentlicht. // rf: https://en.wikipedia.org/wiki/FreeBSD

[1. September 2002]

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

Die GNU-Pakete fileutils, textutils und sh-utils (siehe "Shellutils" am 16. Juli 1991 oben) wurden in einem einzigen Paket zusammengeführt, das als GNU-Coreutils bezeichnet wird.

Insgesamt envvergleichen Use Cases mit printenv:

  1. Druckumgebungsvariablen, printenvkönnen aber das Gleiche tun
  2. Deaktivieren Sie die eingebaute Shell, können Sie aber auch mit cmd erreichen enable.
  3. variabel aber sinnlos eingestellt aufgrund mancher schalen kann man es schon ohne envzb

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

    / tmp

  4. #!/usr/bin/env pythonHeader, aber immer noch nicht portierbar, wenn envnicht in / usr / bin

  5. env -i, deaktiviere alle env. Ich fand es nützlich, die kritischen Umgebungsvariablen für ein bestimmtes Programm herauszufinden, damit es ausgeführt werden kann crontab. zB [1] Im interaktiven Modus ausführen, declare -p > /tmp/d.shum Attributvariablen zu speichern. [2] /tmp/test.shSchreiben Sie in: . /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg[3] Führen Sie nun env -i bash /tmp/test.sh[4] aus. Wenn das Anzeigen des Bildes erfolgreich ist, entfernen Sie die Hälfte der Variablen in /tmp/d.shund führen Sie es env -i bash /tmp/test.sherneut aus. Wenn etwas fehlgeschlagen ist, machen Sie es rückgängig. Wiederholen Sie den Schritt, um ihn einzugrenzen. [5] Schließlich finde ich heraus, dass es eogerforderlich ist $DISPLAY, hineinzulaufen crontab, und mangels $DBUS_SESSION_BUS_ADDRESSWillens wird die Anzeige des Bildes verlangsamt.

  6. target_PATH="$PATH:$(sudo printenv PATH)";ist nützlich, um den Root-Pfad direkt zu verwenden, ohne die Ausgabe von envoder weiter analysieren zu müssen printenv.

z.B:

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:~$
林果 林果
quelle
4
Schöne Geschichtsstunde.
Ouki
21

Mit einer anderen Sichtweise (von FreeBSD aus) haben Sie:

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

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

Daher haben diese Befehle möglicherweise den gleichen Effekt ohne Argument, aber der printenveinzige Zweck besteht darin, die aktuellen Umgebungsschlüssel / -werte anzuzeigen envund gleichzeitig eine Umgebung festzulegen, bevor eine andere Binärdatei / ein anderes Skript / was auch immer aufgerufen wird.

Ist das so klarer?

Um mehr zu wissen:

Ouki
quelle
2
Über die angegebenen Links: Der envBefehl wurde in 4.4BSD angezeigt. Die Optionen -P, -S und -v wurden in FreeBSD 6.0 hinzugefügt. Der printenvBefehl erschien in 3.0BSD. Der historische Grund scheint also der printenvzuerst angekommene zu sein.
mcmlxxxvi
3

Aus Manpages:

Führen Sie ein Programm in einer geänderten Umgebung aus

...

printenv - druckt die gesamte Umgebung oder einen Teil davon

Sollte ziemlich erklärend sein.

UVV
quelle
4
aber ich verstehe es nicht ...
mikeserv
Ich nehme an, dass env vor printenv kommt. Warum also eine andere Binärdatei erstellen? Dies ist nicht dasselbe mit dem, was 'll' zu 'ls' macht, da 'll' keine Binärdatei ist und keine Manpage hat.
WiSaGaN
@mikeserv printenvdruckt nur alle Variablen der aktuellen Umgebung. Mit können envSie bei Bedarf die gleiche Umgebung mit einigen Änderungen vorbereiten und eine App darin ausführen.
UVV
@WiSaGaN Dein Vergleich ist nicht wirklich korrekt. lsist eine Binärdatei, ist aber llein allgemeiner Alias, der normalerweise nur erweitert wird ls -l. printenvund es envgibt zwei verschiedene Binärdateien, ich bin mir nicht sicher, welche zuerst eingeführt wurde. Weitere Beispiele finden Sie hier: gnu.org/software/coreutils/manual/html_node/env-invocation.html
UVV
1
@mikeserv, siehe den Mouseover-Text auf diesem Comic . :)
Wildcard
3

Genau genommen envhandelt es sich um eine Binärdatei mit einer Vielzahl von Funktionen, von denen eine Umgebungsvariablen printenvdruckt , während nur Umgebungsvariablen gedruckt werden.

Zusammenfassend lässt sich sagen, dass Sie, wenn Sie an die Arbeit mit env gewöhnt sind, envdiese drucken müssen (weil Sie das gewohnt sind). Andernfalls werden Sie sich in der Regel printenvschneller daran erinnern .

Es gibt praktisch keine Unterschiede, wenn es um printenvvs geht, envnur um das Drucken von Umgebungsvariablen. Ich habe gerade nachgesehen, und env ist etwas schwerer (ca. 5 zusätzliche KB), und die Leistung (mit der Zeit) scheint genau gleich zu sein.

Hoffe das klärt es aus! :)

David González Ruiz
quelle
-1

Wenn Sie wirklich wissen möchten, wie unterschiedlich die Ausgabe der beiden Binärdateien ist, unabhängig vom Verlauf und dem Erbe der beiden Binärdateien, können Sie einige Dienstprogramme ausführen, um diesen Unterschied zu messen. Unter Debian habe ich einige Dinge ausgeführt, die je nach benutzerdefinierten Umgebungsvariablen unterschiedlich sein werden:

env |wc -l
printenv |wc -l

Beide meine Ausgabe hat 41 Zeilen

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

Ausgabe: 41c41 <_ = / usr / bin / env ---

_ = / usr / bin / printenv

Sie sehen also, dass es in den beiden eine andere Zeile gibt und diese Zeile die Nummer 41 ist, in der die im Befehl verwendete Binärdatei festgelegt ist. Ohne zusätzliche Argumente melden diese für mich nahezu identische Informationen.

Jäger
quelle