Qual è la differenza tra 'env' e 'printenv'?


67

Qual è la differenza tra i due comandi enve printenv? Entrambi mostrano le variabili di ambiente e l'output è esattamente lo stesso a parte _.

Ci sono ragioni storiche per cui ci sono due comandi anziché uno?

Risposte:


49

Ci sono ragioni storiche per cui ci sono due comandi anziché uno?

C'era solo la storia.

  1. Bill Joy scrisse la prima versione del printenvcomando nel 1979 per BSD.
  2. UNIX System III ha introdotto il envcomando nel 1980.
  3. GNU ha seguito UNIX System envnel 1986.
  4. BSD ha seguito il sistema GNU / UNIX envnel 1988.
  5. MINIX ha seguito quelli di BSD printenvnel 1988.
  6. GNU ha seguito MINX / BSD printenvnel 1989.
  7. Utilità di programmazione della shell GNU 1.0 incluse printenve envnel 1991.
  8. GNU Shell Utilities si è fusa in coreutils GNU nel 2002, che era ciò che oggi si può facilmente trovare in GNU / Linux.

Si noti che il "seguito" non significa che il codice sorgente fosse lo stesso, probabilmente sono stati riscritti per evitare una causa di licenza.

Quindi la ragione per cui esistevano entrambi i comandi è perché quando Bill Joy scrisse printenvquella volta, il envnon esiste ancora. Dopo 10 anni di fusione / compatibilità e GNU, ora vedi entrambi i comandi simili nella stessa pagina.

Questa cronologia indicava quanto segue: (Provo a ridurre al minimo la risposta e quindi fornisce solo 2 codice sorgente essenziale qui, il resto è possibile fare clic sui collegamenti allegati per vedere)

[autunno del 1975]

Arrivarono nell'autunno del 1975 anche due dottorandi inosservati, Bill Joy e Chuck Haley; entrambi si interessarono immediatamente al nuovo sistema. Inizialmente iniziarono a lavorare su un sistema Pascal che Thompson aveva violato insieme mentre gironzolava nella sala macchine 11/70.

[1977]

Joy iniziò a compilare la prima Berkeley Software Distribution (1BSD), che fu rilasciata il 9 marzo 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Febbraio 1979]

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

Difficile da determinare rilasciato in 2BSD O 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Giugno 1980]

UNIX Release 3.0 O "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 primo manuale printenv // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 ma non riesco a trovare il manuale relativo a env , il più vicino è getenv e environment // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man

[1986]

Prima versione di 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 rilasciato // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum ha scritto un clone di UNIX, chiamato MINIX (MINi-unIX), per il PC IBM. Era rivolto a studenti e altri che volevano imparare come funzionava un sistema operativo.

[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 ottobre 1988]

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

... 32932 190 /minix/commands/printenv.c //printenv.c esistono già

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

[1989]

Prima versione di GNU printenv, fare riferimento a [12 agosto 1993].

[16 luglio 1991]

"Shellutils" - Rilasciate le utility di programmazione della shell GNU 1.0 // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

I programmi in questo pacchetto sono:

basename data dirname env expr gruppi id logname pathchk printenv printf sleep tee tty whoami sì nice nohup stty uname

[12 agosto 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 che ha trovato sul codice sorgente DSLinux nel 2006 // rf: (Google) cache: 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

[Novembre 1993]

La prima versione di FreeBSD è stata rilasciata. // rf: https://en.wikipedia.org/wiki/FreeBSD

[1 settembre 2002]

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

I pacchetti fileutils, textutils e sh-utils GNU (vedi "Shellutils" al 16 luglio 1991 sopra) sono stati uniti in uno, chiamato coreutils GNU.

Complessivamente, i envcasi d'uso si confrontano con printenv:

  1. stampa variabili d'ambiente, ma printenvpuò fare lo stesso
  2. Disabilita la shell integrata ma può enablefarlo anche con cmd.
  3. impostare variabile ma inutile a causa di alcune shell già può farlo senza env, ad es

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

    / tmp

  4. #!/usr/bin/env pythonintestazione, ma comunque non portatile se envnon in / usr / bin

  5. env -i, disabilita tutto env. Ho trovato utile capire le variabili di ambiente critiche per determinati programmi per eseguirlo crontab. es. [1] In modalità interattiva, esegui declare -p > /tmp/d.shper memorizzare le variabili degli attributi. [2] In /tmp/test.sh, scrivi: . /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg[3] Ora esegui env -i bash /tmp/test.sh[4] Se riesce a visualizzare l'immagine, rimuovi metà delle variabili /tmp/d.shed esegui di env -i bash /tmp/test.shnuovo. Se qualcosa non ha funzionato, annullalo. Ripetere il passaggio per restringere. [5] Alla fine ho capito che eogbisogna $DISPLAYcorrere crontab, e in assenza di $DBUS_SESSION_BUS_ADDRESSciò rallenterà la visualizzazione dell'immagine.

  6. target_PATH="$PATH:$(sudo printenv PATH)";è utile per utilizzare direttamente il percorso di root senza dover analizzare ulteriormente l'output di envo printenv.

per esempio:

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
Bella lezione di storia.
Ouki,

21

Avendo un diverso punto di vista (da FreeBSD), hai:

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

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

Quindi questi comandi potrebbero avere lo stesso effetto senza argomenti, ma l' printenvunico scopo è quello di visualizzare la chiave / i valori dell'ambiente corrente mentre l' envobiettivo è di impostare un ambiente prima di chiamare un altro binario / script / qualunque cosa.

È più chiaro in questo modo?

Per saperne di più:


2
Dai collegamenti forniti: il envcomando è apparso in 4.4BSD. Le opzioni -P, -S e -v sono state aggiunte in FreeBSD 6.0. Il printenvcomando è apparso in 3.0BSD. Quindi la ragione storica sembra essere quella printenvarrivata per prima.
mcmlxxxvi,


3

Dalle pagine man:

env - esegue un programma in un ambiente modificato

...

printenv - stampa tutto o parte dell'ambiente

Dovrebbe essere piuttosto esplicativo.


4
ma non capisco ...
Mikeserv,

Suppongo che env venga prima di printenv. Quindi perché creare un altro binario? Questo non è lo stesso di ciò che "ll" sarà "ls" poiché "ll" non è un file binario e non ha una pagina man.
WiSaGaN

@mikeserv printenvstampa solo tutte le variabili dell'ambiente corrente. Con envte puoi preparare lo stesso ambiente con alcune modifiche se necessario ed eseguire un'app al suo interno.
UVV

@WiSaGaN il tuo confronto non è proprio corretto. lsè un file binario, ma llè un alias comune, che di solito si espande ls -l. printenve envsono due binari diversi, non sono sicuro di quale sia stato introdotto per primo però. Puoi vedere altri esempi qui gnu.org/software/coreutils/manual/html_node/env-invocation.html
UVV

1
@mikeserv, vedi il testo del passaggio del mouse su questo fumetto . :)
Wildcard

3

Parlando rigorosamente di funzionalità, envè un file binario con una vasta gamma di funzionalità, una delle quali è la stampa di variabili d'ambiente, mentre printenvstampa solo variabili d'ambiente.

Riassumendo, se sei abituato a lavorare con env, andrai avanti con envla loro stampa (perché è quello a cui sei abituato) e se non lo sei, in genere ti ricorderai printenvpiù velocemente.

Non ci sono praticamente differenze quando si parla di printenvvs envsolo per la stampa di variabili ambientali. Ho appena controllato ed env è leggermente più pesante (circa 5 KB in più) e le loro prestazioni (nel tempo) sembrano essere esattamente le stesse.

Spero che questo lo chiarisca! :)


-1

Se vuoi davvero sapere quanto è diverso l'output dei due binari indipendentemente dalla storia e dall'eredità di essi, puoi eseguire alcune utility per valutare questa differenza. Su debian ho eseguito alcune cose che saranno diverse a seconda di eventuali variabili ambientali personalizzate:

env |wc -l
printenv |wc -l

Entrambi i miei output hanno 41 righe

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

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

_ = / Usr / bin / printenv

Quindi vedi che c'è una linea diversa nelle due e quella linea è il numero 41 che immagino stabilisce il binario usato nel comando. Senza ulteriori argomenti, questi riportano informazioni identiche virtuali per me.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.