web-dev-qa-db-fra.com

Quelle est la différence entre «env» et «printenv»?

Quelle est la différence entre les deux commandes env et 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 lesquelles il y a deux commandes au lieu d'une?

75
WiSaGaN

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

Il y avait juste une histoire.

  1. Bill Joy a écrit la première version de la commande printenv en 1979 pour BSD.
  2. UNIX System III a introduit la commande env en 1980.
  3. GNU a suivi le env d'UNIX System en 1986.
  4. BSD a suivi le env du système GNU/UNIX en 1988.
  5. MINIX a suivi le printenv de BSD en 1988.
  6. GNU a suivi printenv de MINX/BSD en 1989.
  7. Les utilitaires de programmation GNU Shell 1.0 comprenaient printenv et env en 1991.
  8. GNU Shell Utilities a fusionné en GNU coreutils en 2002, ce qui était ce que vous pouviez facilement trouver dans GNU/Linux de nos jours.

Notez que le "suivi" ne signifie pas que le code source était le même, probablement ils ont été réécrits pour éviter un procès de licence.

Donc, la raison pour laquelle les deux commandes existaient est parce que lorsque Bill Joy a écrit printenv à ce moment-là, le env n'existe pas encore. Après 10 ans de fusion/compatibilité et GNU rencontré, vous voyez maintenant les deux commandes similaires sur la même page.

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

[automne 1975]

Arrivant également à l'automne 1975, deux étudiants diplômés inaperçus, Bill Joy et Chuck Haley; ils se sont tous deux intéressés immédiatement au nouveau système. Au début, ils ont commencé à travailler sur un système Pascal que Thompson avait piraté ensemble en traînant dans la salle des machines 11/70.

[1977]

Joy a commencé à compiler la première distribution de logiciel Berkeley (1BSD), qui a été publiée 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?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 à déterminer publié dans 2BSD OR 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[juin 1980]

UNIX version 3.0 OR "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 premier manuel printenv // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 mais je peux 'ai pas trouvé de manuel lié à 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 1st sorti // 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 à ceux qui souhaitaient apprendre comment fonctionnait 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" - GNU Utilitaires de programmation Shell 1.0 publiés // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc =

Les programmes de ce package sont:

nom de base date dirname env expr groups id logname pathchk printenv printf sleep tee tty whoami oui Nice 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 trouvé sur le code source DSLinux en 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 première version de FreeBSD est sortie. // 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 packages GNU fileutils, textutils et sh-utils (voir "Shellutils" au 16 juillet 1991 ci-dessus) ont été fusionnés en un seul, appelé GNU coreutils.

Globalement, env cas d'utilisation se comparent à printenv:

  1. imprimer les variables d'environnement, mais printenv peut faire de même
  2. Désactivez le shell intégré, mais vous pouvez également le faire avec enable cmd.
  3. définir une variable mais inutile car certains shells peuvent déjà le faire sans env, par exemple.

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

    / tmp

  4. En-tête #!/usr/bin/env python, Mais toujours pas portable si env pas dans/usr/bin

  5. env -i, Désactivez tout env. J'ai trouvé utile de comprendre les variables d'environnement critiques de certains programmes pour les faire fonctionner à partir de crontab. par exemple. [1] En mode interactif, exécutez declare -p > /tmp/d.sh Pour 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] S'il réussit à afficher l'image, supprimez la moitié des variables dans /tmp/d.sh et exécutez à nouveau env -i bash /tmp/test.sh. Si quelque chose a échoué, annulez-le. Répétez l'étape pour réduire. [5] Enfin, je pense que eog nécessite que $DISPLAY S'exécute dans crontab et que l'absence de $DBUS_SESSION_BUS_ADDRESS Ralentira l'affichage de l'image.

  6. target_PATH="$PATH:$(Sudo printenv PATH)"; est utile pour utiliser directement le chemin racine sans avoir à analyser davantage la sortie de env ou 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:~$
58
林果皞

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 printenv le seul but est d'afficher la clé/les valeurs d'environnement actuelles tandis que env le but de 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:

22
Ouki

envest POSIX 7, printenvn'est pas (GNU Coreutils dans Ubuntu 15.10).

Depuis les pages de manuel:

env - exécuter un programme dans un environnement modifié

...

printenv - imprime tout ou partie de l'environnement

Devrait être assez explicatif.

4
UVV

Parlant strictement de fonctionnalités, env est un binaire avec un ensemble énorme de fonctionnalités, l'une d'entre elles étant l'impression de variables d'environnement, tandis que printenv imprime simplement des variables d'environnement.

En résumé, si vous avez l'habitude de travailler avec env, vous irez avec env pour les imprimer (car c'est ce à quoi vous êtes habitué) et si vous ne l'êtes pas, vous vous souviendrez généralement printenv plus rapidement .

Il n'y a pratiquement aucune différence lorsque l'on parle de printenv vs env pour l'impression de variables d'environnement uniquement. Je viens de vérifier et env est légèrement plus lourd (environ 5 Ko supplémentaires), et leurs performances (dans le temps) semblent être exactement les mêmes.

J'espère que cela le clarifie! :)

3