¿Cuál es la diferencia entre 'env' y 'printenv'?

67

¿Cuál es la diferencia entre los dos comandos envy printenv? Ambos muestran las variables de entorno, y la salida es exactamente la misma aparte de _.

¿Hay alguna razón histórica para que haya dos comandos en lugar de uno?

WiSaGaN
fuente

Respuestas:

49

¿Hay alguna razón histórica para que haya dos comandos en lugar de uno?

Solo había manera de la historia.

  1. Bill Joy escribió la primera versión del printenvcomando en 1979 para BSD.
  2. El sistema UNIX III introdujo el envcomando en 1980.
  3. GNU siguió el Sistema UNIX enven 1986.
  4. BSD siguió el sistema GNU / UNIX enven 1988.
  5. MINIX siguió a BSD printenven 1988.
  6. GNU siguió a MINX / BSD printenven 1989.
  7. Utilidades de programación GNU shell 1.0 incluidas printenvy enven 1991.
  8. GNU Shell Utilities se fusionó con GNU coreutils en 2002, que era lo que se podía encontrar fácilmente en GNU / Linux hoy en día.

Tenga en cuenta que "seguido" no significa que el código fuente era el mismo, probablemente fueron reescritos para evitar una demanda de licencia.

Entonces, la razón de por qué ambos comandos existieron es porque cuando Bill Joy escribió printenvesa vez, el envtodavía no existe. Después de 10 años de fusión / compatibilidad y GNU lo encuentra, ahora está viendo ambos comandos similares en la misma página.

Este historial indica lo siguiente: (Intento minimizar la respuesta y, por lo tanto, solo proporciono 2 códigos fuente esenciales aquí, el resto puede hacer clic en los enlaces adjuntos para ver)

[otoño de 1975]

También llegaron en el otoño de 1975 dos estudiantes graduados inadvertidos, Bill Joy y Chuck Haley; Ambos se interesaron de inmediato por el nuevo sistema. Inicialmente comenzaron a trabajar en un sistema Pascal que Thompson había pirateado mientras se paseaba por la sala de máquinas 11/70.

[1977]

Joy comenzó a compilar el primer Berkeley Software Distribution (1BSD), que se lanzó el 9 de marzo de 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Febrero de 1979]

1979 (ver "Bill Joy, UCB febrero, 1979") / 1980 (ver "copyright [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? archivo = 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]

Difícil de determinar publicado en 2BSD O 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[Junio ​​de 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 first printenv manual // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 pero no encuentro el manual relacionado con env , el más cercano es getenv y environmental // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man

[1986]

Primera versión 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 lanzado // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum escribió un clon de UNIX, llamado MINIX (MINi-unIX), para la PC de IBM. Estaba dirigido a estudiantes y otras personas que querían aprender cómo funcionaba 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 de octubre de 1988]

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

... 32932 190 /minix/commands/printenv.c //printenv.c ya existen

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

[1989]

Primera versión de GNU printenv, consulte [12 de agosto de 1993].

[16 de julio de 1991]

"Shellutils" - Utilidades de programación de shell GNU 1.0 lanzadas // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

Los programas en este paquete son:

basename date dirname env expr grupos id logname pathchk printenv printf sleep tee tty whoami sí nice nohup stty uname

[12 de agosto de 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 que se encontró en el código fuente de DSLinux en 2006 // rf: (Google) caché: 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

[Noviembre de 1993]

Se lanzó la primera versión de FreeBSD. // rf: https://en.wikipedia.org/wiki/FreeBSD

[1 de septiembre de 2002]

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

Los paquetes GNU fileutils, textutils y sh-utils (ver "Shellutils" al 16 de julio de 1991 arriba) se han fusionado en uno, llamado GNU coreutils.

En general, los envcasos de uso se comparan con printenv:

  1. variables de entorno de impresión, pero printenvpueden hacer lo mismo
  2. Deshabilite la construcción de shell, pero también puede lograr con enablecmd.
  3. establecer variable pero sin sentido debido a que algunos shells ya pueden hacerlo sin env, por ejemplo

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

    / tmp

  4. #!/usr/bin/env pythonencabezado, pero aún no es portátil si envno está en / usr / bin

  5. env -i, deshabilitar todo env. Me resultó útil descubrir las variables de entorno críticas para que cierto programa lo ejecute crontab. ej. [1] En modo interactivo, ejecutar declare -p > /tmp/d.shpara almacenar variables de atributos. [2] En /tmp/test.sh, escriba: . /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg[3] Ahora ejecute env -i bash /tmp/test.sh[4] Si tiene éxito para mostrar la imagen, elimine la mitad de las variables /tmp/d.shy env -i bash /tmp/test.shvuelva a ejecutar . Si algo falla, deshazlo. Repita el paso para reducir. [5] Finalmente, me doy cuenta de que es eognecesario $DISPLAYcorrer crontab, y ausente $DBUS_SESSION_BUS_ADDRESSdisminuirá la visualización de la imagen.

  6. target_PATH="$PATH:$(sudo printenv PATH)";es útil para usar directamente la ruta raíz sin tener que analizar más la salida de envo printenv.

p.ej:

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:~$
林果 皞
fuente
44
Buena lección de historia.
Ouki
21

Teniendo un punto de vista diferente (de FreeBSD), tiene:

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.

Por lo tanto, estos comandos pueden tener el mismo efecto sin argumento, pero el printenvúnico propósito es mostrar la clave / valores del entorno actual mientras envse establece un entorno antes de llamar a otro binario / script / lo que sea.

¿Está más claro de esta manera?

Para saber más:

Ouki
fuente
2
Desde los enlaces provistos: El envcomando apareció en 4.4BSD. Las opciones -P, -S y -v se agregaron en FreeBSD 6.0. El printenvcomando apareció en 3.0BSD. Entonces, la razón histórica parece ser que printenvllegó primero.
mcmlxxxvi
5

env es POSIX 7 ,printenv no lo es (GNU Coreutils en Ubuntu 15.10).

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
fuente
3

De páginas de manual:

env: ejecuta un programa en un entorno modificado

...

printenv - imprime todo o parte del entorno

Debería ser bastante explicativo.

UVV
fuente
44
pero no lo entiendo ...
mikeserv
Supongo que env viene antes de printenv. Entonces, ¿por qué hacer otro binario? Esto no es lo mismo con lo que 'll' a 'ls' ya que 'll' no es un binario y no tiene una página de manual.
WiSaGaN
@mikeserv printenvsolo imprime todas las variables del entorno actual. Con envusted puede preparar el mismo entorno con algunas modificaciones si es necesario y ejecutar una aplicación en él.
UVV
@WiSaGaN su comparación no es realmente correcta. lses un binario, pero lles un alias común, que generalmente solo se expande a ls -l. printenvy envson dos binarios diferentes, aunque no estoy seguro de cuál se introdujo primero. Puede ver algunos ejemplos más aquí gnu.org/software/coreutils/manual/html_node/env-invocation.html
UVV
1
@mikeserv, mira el texto al pasar el mouse sobre este cómic . :)
Comodín el
3

Hablando estrictamente de funcionalidades, enves un binario con un gran conjunto de características, una de ellas es la impresión de variables de entorno, mientras que printenvsolo imprime variables de entorno.

Resumiendo, si estás acostumbrado a trabajar con env, irás enva imprimirlos (porque a eso estás acostumbrado) y si no lo estás, normalmente recordarás printenvmás rápido.

Prácticamente no hay diferencias cuando se habla de printenvvs envsolo para imprimir variables ambientales. Acabo de comprobar y env es un poco más pesado (aproximadamente 5 KB adicionales), y su rendimiento (a tiempo) parece ser exactamente el mismo.

Espero que esto lo aclare! :)

David González Ruiz
fuente
-1

Si realmente desea saber qué tan diferente es la salida de los dos binarios, independientemente del historial y el legado de los mismos, puede ejecutar algunas utilidades para medir esta diferencia. En Debian ejecuté algunas cosas que serán diferentes dependiendo de cualquier variable ambiental personalizada:

env |wc -l
printenv |wc -l

Tanto mi salida tiene 41 líneas

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

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

_ = / usr / bin / printenv

Entonces ves que hay una línea diferente en las dos y esa línea es la número 41, que supongo que estipula el binario utilizado en el comando. Sin argumentos adicionales, estos informan información virtual idéntica para mí.

cazador
fuente