Quelle est la difference entre 'env' et 'printenv'?


67

Quelle est la différence entre les deux commandes envet printenv? Ils affichent tous les deux les variables d'environnement et la sortie est exactement la même, à part _.

Y a-t-il des raisons historiques pour qu'il y ait deux commandes au lieu d'une?

Réponses:


49

Y a-t-il des raisons historiques pour qu'il y ait deux commandes au lieu d'une?

Il y avait juste la manière de l'histoire.

  1. Bill Joy a écrit la première version de printenvcommande en 1979 pour BSD.
  2. UNIX System III a introduit le envcommandement en 1980.
  3. GNU a suivi les systèmes UNIX enven 1986.
  4. BSD a suivi les systèmes GNU / UNIX enven 1988.
  5. MINIX a suivi BSD printenven 1988.
  6. GNU a suivi MINX / BSD printenven 1989.
  7. Utilitaires de programmation du shell GNU 1.0 inclus printenvet enven 1991.
  8. GNU Shell Utilities a fusionné dans GNU coreutils en 2002, ce que l’on pouvait facilement trouver dans GNU / Linux de nos jours.

Notez que le mot "suivi" ne signifie pas que le code source était le même, ils ont probablement été réécrits pour éviter une poursuite en licence.

La raison pour laquelle les deux commandes existaient est donc parce que lorsque Bill Joy a écrit printenvcette époque, le envn'existe pas encore. Après 10 ans de fusion / compatibilité et de GNU, vous voyez maintenant les deux commandes similaires sur la même page.

Cet historique indique comme suit: (J'essaie de minimiser la réponse et ne fournit donc que 2 codes sources essentiels ici, le reste vous pouvez cliquer sur les liens attachés pour voir)

[automne 1975]

Arrivés à l’automne 1975, Bill Joy et Chuck Haley, deux étudiants diplômés de troisième cycle, ont également été remarqués. ils ont tous deux un intérêt immédiat pour le nouveau système. Initialement, ils ont commencé à travailler sur un système Pascal que Thompson avait piraté ensemble pendant qu'ils traînaient dans la salle des machines 11/70.

[1977]

Joy a commencé à compiler la première version de Berkeley Software Distribution (1BSD), sortie le 9 mars 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Février 1979]

1979 (voir "Bill Joy, UCB février 1979") / 1980 (voir "copyright [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? fichier = 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 à déterminer publié dans 2BSD OU 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Juin 1980]

UNIX version 3.0 OU "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]

Premier manuel d'impression BSD // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 mais je n'ai pas trouvé de manuel relatif à env , le plus proche est getenv et environ // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man

[1986]

Première version de GNU env// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/env.c

[1987]

MINIX 1ere sortie // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum a écrit un clone d'UNIX, appelé MINIX (MINi-unIX), pour le PC IBM. Il était destiné aux étudiants et à d'autres personnes souhaitant apprendre le fonctionnement d'un système d'exploitation.

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

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

... 32932 190 /minix/commands/printenv.c //printenv.c existe déjà

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

[1989]

Première version de GNU printenv, voir [12 août 1993].

[16 juillet 1991]

"Shellutils" - Publication de la version 1.0 des utilitaires de programmation du shell GNU // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

Les programmes de ce paquet sont:

nom de base date dirname env env groupes id id logname pathchk printenv printf sommeil tee tty whoami oui gentil nohup stty uname

[12 août 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 qui a trouvé le code source DSLinux en 2006 // rf: cache (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

[Novembre 1993]

La première version de FreeBSD a été publiée. // rf: https://en.wikipedia.org/wiki/FreeBSD

[1er septembre 2002]

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

Les paquets GN fileutils, textutils et sh-utils (voir "Shellutils" au 16 juillet 1991 ci-dessus) ont été fusionnés en un seul, appelé GNU coreutils.

Dans l’ensemble, envles cas d’utilisation se comparent avec printenv:

  1. variables d’environnement d’impression, mais printenvpeut en faire autant
  2. Désactiver shell intégré mais peut atteindre avec enablecmd aussi.
  3. définir variable mais inutile en raison de certains coquilles peut déjà le faire sans env, par exemple

    $ HOME = / dev HOME = / tmp UTILISATEUR = racine / bin / bash -c "cd ~; pwd"

    / tmp

  4. #!/usr/bin/env pythonen-tête, mais toujours pas portable sinon envdans / usr / bin

  5. env -i, désactivez toutes les env. J'ai trouvé utile de déterminer les variables d'environnement critiques pour que certains programmes l'exécutent crontab. Exemple: [1] En mode interactif, exécuter declare -p > /tmp/d.shpour stocker les variables d'attribut. [2] Dans /tmp/test.sh, écrivez: . /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg[3] Maintenant, exécutez env -i bash /tmp/test.sh[4] Si vous réussissez à afficher une image, supprimez la moitié des variables /tmp/d.shet exécutez-le à env -i bash /tmp/test.shnouveau. Si quelque chose a échoué, annulez-le. Répétez cette étape pour affiner. [5] Enfin, je comprends qu'il eogfaut $DISPLAYcourir crontab, et sans $DBUS_SESSION_BUS_ADDRESSralentir l'affichage de l'image.

  6. target_PATH="$PATH:$(sudo printenv PATH)";est utile pour utiliser directement le chemin racine sans avoir à analyser plus avant le résultat de envou printenv.

par exemple:

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
Belle leçon d'histoire.
Ouki

21

Ayant un point de vue différent (de FreeBSD), vous avez:

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

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

Donc, ces commandes peuvent avoir le même effet sans argument, mais le printenvseul but est d’afficher la clé / les valeurs de l’environnement actuel tout en envvisant à définir un environnement avant d’appeler un autre binaire / script / peu importe.

Est-ce plus clair de cette façon?

Pour en savoir plus:


2
A partir des liens fournis: La envcommande est apparue dans 4.4BSD. Les options -P, -S et -v ont été ajoutées dans FreeBSD 6.0. La printenvcommande est apparue dans 3.0BSD. Donc, la raison historique semble être celle qui printenvest arrivée en premier.
mcmlxxxvi


3

Des pages de manuel:

env - lance un programme dans un environnement modifié

...

printenv - imprime tout ou partie de l'environnement

Devrait être assez explicatif.


4
mais je ne comprends pas ...
mikeserv

Je suppose que env vient avant printenv. Alors pourquoi faire un autre binaire? Ce n'est pas la même chose avec ce qui va de "ls" puisque "ll" n'est pas un binaire et n'a pas de page de manuel.
WiSaGaN

@mikeserv printenvn'imprime que toutes les variables de l'environnement actuel. Avec envvous pouvez préparer le même environnement avec quelques modifications si nécessaire et y exécuter une application.
UVV

@WiSaGaN votre comparaison n'est pas vraiment correcte. lsest un binaire, mais llest un alias commun, qui se développe généralement en ls -l. printenvet envsont deux binaires différents, je ne suis pas sûr de savoir lequel a été introduit en premier. Vous pouvez voir quelques exemples supplémentaires ici gnu.org/software/coreutils/manual/html_node/env-invocation.html
UVV

1
@mikeserv, voir le texte au survol de cette bande dessinée . :)
Wildcard

3

Parler strictement de fonctionnalités, envest un binaire avec un vaste ensemble de fonctionnalités, l’une d’elles étant l’impression de variables d’environnement, alors printenvqu’il n’imprime que les variables d’environnement.

En résumé, si vous avez l'habitude de travailler avec env, vous irez les envimprimer (parce que c'est ce que vous avez l'habitude de faire) et si vous ne l'êtes pas, vous vous en souviendrez printenvplus rapidement.

Il n'y a pratiquement aucune différence entre printenvvs envet simplement imprimer des variables environnementales. Je viens de vérifier et env est légèrement plus lourd (environ 5 Ko supplémentaires), et leur performance (dans le temps) semble être exactement la même.

J'espère que ça efface! :)


-1

Si vous voulez vraiment savoir en quoi les résultats des deux fichiers binaires sont différents, indépendamment de leur historique et de leur héritage, vous pouvez exécuter quelques utilitaires pour évaluer cette différence. Sur debian, j’ai fait quelques choses qui seront différentes selon les vars environnementaux personnalisés:

env |wc -l
printenv |wc -l

Ma sortie a 41 lignes

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

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

_ = / usr / bin / printenv

Donc, vous voyez qu'il y a une ligne différente dans les deux et que cette ligne est le numéro 41 qui, je suppose, stipule le binaire utilisé dans la commande. Sans arguments supplémentaires, ceux-ci rapportent des informations virtuellement identiques pour moi.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.