Pregunta:
¿Cuál es la diferencia entre los dos comandos env
y printenv
? Ambos muestran las variables de entorno y el resultado es exactamente el mismo, aparte de _
.
¿Existen razones históricas para que haya dos comandos en lugar de uno?
Respuesta:
¿Existen razones históricas para que haya dos comandos en lugar de uno?
Había, simplemente estilo histórico.
- Bill Joy escribió la primera versión del comando
printenv
en 1979 para BSD. - UNIX System III introdujo el comando
env
en 1980. - GNU siguió al
env
del sistema UNIX en 1986. - BSD siguió al
env
del sistema GNU / UNIX en 1988. - MINIX siguió el
printenv
de BSD en 1988. - GNU seguido de MINX / BSD
printenv
en 1989. - Las utilidades de programación de shell GNU 1.0 incluyeron
printenv
yenv
en 1991. - GNU Shell Utilities se fusionó con GNU coreutils en 2002, que es lo que se encuentra actualmente en GNU / Linux.
Tenga en cuenta que el "seguido" no significa que el código fuente sea el mismo, probablemente fueron reescrito para evitar demandas por licencias.
Entonces, la razón por la que existieron ambos comandos es porque Bill Joy escribió printenv
incluso antes de que existiera env
. 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 se indica de la siguiente manera: (Traté de minimizar la respuesta y solo proporcioné 2 fragmentos de código fuente esenciales aquí. El resto puede hacer clic en los enlaces adjuntos para ver más)
[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 en el nuevo sistema. Inicialmente, comenzaron a trabajar en un sistema Pascal que Thompson había pirateado mientras merodeaban por la sala de máquinas 11/70.
[1977]
Joy comenzó a compilar la primera distribución de software de Berkeley (1BSD), que se publicó el 9 de marzo de 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Febrero de 1979]
1979 (ver "Bill Joy, UCB febrero de 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
-
3BSD El comando printenv apareció en 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD introducido en 1979 // rf: http://gunkies.org/wiki/3_BSD
-
2BSD El comando printenv apareció por primera vez en 2BSD // rf: http://man.openbsd.org/printenv.1
[Junio de 1980]
Versión 3.0 de UNIX O "Sistema III de UNIX" // 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
No pude encontrar el manual relacionado con env, pero el más cercano es getenv y environment //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 1er lanzado // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum
- Tanenbaum escribió un clon de UNIX, llamado MINIX (MINi-unIX), para IBM PC. 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
… 32932190 /minix/commands/printenv.c //printenv.c ya existe
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
La primera versión de GNU printenv
, consulte [12 de agosto de 1993].
[16 de julio de 1991]
"Shellutils": lanzamiento de las utilidades de programación de shell de GNU 1.0 // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Los programas de este paquete son:
basename date dirname env expr grupos id logname pathchk printenv printf sleep tee tty whoami yes 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) 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
[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" del 16 de julio de 1991 más arriba) se han fusionado en uno, llamado GNU coreutils.
En general, los casos de uso de env
se comparan con printenv
:
-
imprimir variables de entorno, pero
printenv
puede hacer lo mismo -
Desactive el shell incorporado, pero también puede lograrlo con
enable
cmd. -
establecer variable pero inútil debido a que algunos shells ya pueden hacerlo sin
env
, por ejemplo$ INICIO = / dev INICIO = / tmp USUARIO = root / bin / bash -c "cd ~; pwd"
/ tmp
-
#!/usr/bin/env python
encabezado de#!/usr/bin/env python
, pero aún no es portátil sienv
no está en / usr / bin -
env -i
, deshabilita todos los env. Encuentro útil averiguar las variables de entorno críticas para cierto programa, para que se ejecute desdecrontab
. Por ejemplo, [1] En modo interactivo, ejecutedeclare -p > /tmp/d.sh
para almacenar variables de atributos. [2] En/tmp/test.sh
, escribir:. /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg
[3] Ahora ejecuteenv -i bash /tmp/test.sh
[4] Si muestra la imagen/tmp/d.sh
, elimine la mitad de las variables en/tmp/d.sh
y ejecuteenv -i bash /tmp/test.sh
nuevo. Si algo falló, deshazlo. Repita el paso para reducir. [5] Finalmente me doy cuenta de queeog
requiere$DISPLAY
para ejecutarse encrontab
, y la ausencia de$DBUS_SESSION_BUS_ADDRESS
ralentizará la visualización de la imagen. -
target_PATH="$PATH:$(sudo printenv PATH)";
Es útil usar directamente la ruta raíz sin tener que analizar más la salida deenv
oprintenv
.
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:~$