¿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 _
.
¿Hay alguna razón histórica para que haya dos comandos en lugar de uno?
Respuesta aceptada:
¿Hay alguna razón histórica para que haya dos comandos en lugar de
uno?
Lo había, solo a la manera de la historia.
- Bill Joy escribió la primera versión de
printenv
comando en 1979 para BSD. - UNIX System III introdujo
env
mando en 1980. - GNU siguió el
env
del sistema UNIX en 1986. - BSD siguió el
env
del sistema GNU/UNIX en 1988. - MINIX siguió el
printenv
de BSD en 1988. - GNU siguió a
printenv
de MINX/BSD en 1989. - Utilidades de programación de shell GNU 1.0 incluidas
printenv
yenv
en 1991. - GNU Shell Utilities se fusionó con GNU coreutils en 2002, que es lo que encuentras en GNU/Linux hoy en día.
Tenga en cuenta que "seguido" no significa que el código fuente sea el mismo, probablemente se reescribieron para evitar demandas por licencias.
Entonces, la razón por la que existían ambos comandos es porque Bill Joy escribió printenv
incluso antes de env
existió.
Después de 10 años de fusión/compatibilidad y GNU lo encontró, 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 que pasaron desapercibidos, Bill Joy y Chuck Haley; ambos tomaron un interés inmediato en el nuevo sistema. Inicialmente, comenzaron a trabajar en un sistema Pascal que Thompson había pirateado mientras merodeaba por la sala de máquinas del 11/70.
Joy comenzó a compilar la primera distribución de software de Berkeley (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 de 1979”) /1980(ver “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);
}
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]
UNIX Versión 3.0 O “UNIX System III” //rf:ftp://pdp11.org.ru/pub/unix-archive/PDP-11/Distributions/usdl/SysIII/
[[email protected] pdp11v3]$ sudo grep -rni printenv . //no such printenv exist.
[[email protected] 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
[[email protected] 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)
[[email protected] pdp11v3]$
[[email protected] 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);
}
[[email protected] pdp11v3]$
BSD primer manual printenv //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 environ //http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
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
MINIX 1er lanzamiento //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.
BSD 1er 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 existe
//rf:http://www.informatica.co.cr/linux/research/1990/0202.htm
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 GNU 1.0
//rf:https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Los programas en este paquete son:
nombre base fecha dirname env expr grupos id logname pathchk printenv printf dormir tee tty whoami sí agradable 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.
...
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-renombrado-a-coreutils
Los paquetes GNU fileutils, textutils y sh-utils (ver "Shellutils" el 16 de julio de 1991 arriba) se fusionaron en uno, llamado GNU coreutils.
En general, env
casos de uso comparar con printenv
:
-
imprimir variables de entorno, pero
printenv
puede hacer lo mismo -
Deshabilite el shell incorporado pero puede lograrlo con
enable
cmd también. -
establece una variable pero no tiene sentido debido a que algunos shells ya pueden hacerlo sin
env
, por ejemplo$ INICIO=/dev INICIO=/tmp USUARIO=raíz /bin/bash -c “cd ~; pwd”
/tmp
-
#!/usr/bin/env python
encabezado, pero aún no es portátil sienv
no en /usr/bin -
env -i
, deshabilite todos los env. Encuentro útil averiguar las variables de entorno críticas para cierto programa, para que se ejecute desdecrontab
. p.ej. [1] En modo interactivo, ejecutedeclare -p > /tmp/d.sh
para almacenar variables de atributos. [2] En/tmp/test.sh
, escriba:. /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg
[3] Ahora ejecuteenv -i bash /tmp/test.sh
[4] Si tiene éxito al mostrar la imagen, elimine la mitad de las variables en/tmp/d.sh
y ejecutaenv -i bash /tmp/test.sh
otra vez. Si algo falla, deshazlo. Repita el paso para reducir. [5] Finalmente descubroeog
requiere$DISPLAY
para ejecutar encrontab
, y ausente de$DBUS_SESSION_BUS_ADDRESS
ralentizará la visualización de la imagen. -
target_PATH="$PATH:$(sudo printenv PATH)";
es útil para usar directamente la ruta raíz sin tener que analizar más la salida deenv
oprintenv
.
por ejemplo:
[email protected]:~$ sudo env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[email protected]:~$ sudo printenv | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[email protected]:~$ sudo printenv PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[email protected]:~$ sudo env PATH
env: ‘PATH’: No such file or directory
[email protected]:~$