Risposte:
Ci sono ragioni storiche per cui ci sono due comandi anziché uno?
C'era solo la storia.
printenv
comando nel 1979 per BSD.env
comando nel 1980.env
nel 1986.env
nel 1988.printenv
nel 1988.printenv
nel 1989.printenv
e env
nel 1991.Si noti che il "seguito" non significa che il codice sorgente fosse lo stesso, probabilmente sono stati riscritti per evitare una causa di licenza.
Quindi la ragione per cui esistevano entrambi i comandi è perché quando Bill Joy scrisse printenv
quella volta, il env
non esiste ancora. Dopo 10 anni di fusione / compatibilità e GNU, ora vedi entrambi i comandi simili nella stessa pagina.
Questa cronologia indicava quanto segue: (Provo a ridurre al minimo la risposta e quindi fornisce solo 2 codice sorgente essenziale qui, il resto è possibile fare clic sui collegamenti allegati per vedere)
[autunno del 1975]
Arrivarono nell'autunno del 1975 anche due dottorandi inosservati, Bill Joy e Chuck Haley; entrambi si interessarono immediatamente al nuovo sistema. Inizialmente iniziarono a lavorare su un sistema Pascal che Thompson aveva violato insieme mentre gironzolava nella sala macchine 11/70.
[1977]
Joy iniziò a compilare la prima Berkeley Software Distribution (1BSD), che fu rilasciata il 9 marzo 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Febbraio 1979]
1979 (vedi "Bill Joy, UCB February, 1979") / 1980 (vedi "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 da determinare rilasciato in 2BSD O 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD Il comando printenv è apparso in 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD introdotto al 1979 // rf: http://gunkies.org/wiki/3_BSD
2BSD Il comando printenv è apparso per la prima volta in 2BSD // rf: http://man.openbsd.org/printenv.1
[Giugno 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 primo manuale printenv // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 ma non riesco a trovare il manuale relativo a env , il più vicino è getenv e environment // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Prima versione di 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 rilasciato // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum
[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 ottobre 1988]
MINIX versione 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c esistono già
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Prima versione di GNU printenv
, fare riferimento a [12 agosto 1993].
[16 luglio 1991]
"Shellutils" - Rilasciate le utility di programmazione della shell GNU 1.0 // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
I programmi in questo pacchetto sono:
basename data dirname env expr gruppi id logname pathchk printenv printf sleep tee tty whoami sì nice nohup stty uname
[12 agosto 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 che ha trovato sul codice sorgente DSLinux nel 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 prima versione di FreeBSD è stata rilasciata. // rf: https://en.wikipedia.org/wiki/FreeBSD
[1 settembre 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
I pacchetti fileutils, textutils e sh-utils GNU (vedi "Shellutils" al 16 luglio 1991 sopra) sono stati uniti in uno, chiamato coreutils GNU.
Complessivamente, i env
casi d'uso si confrontano con printenv
:
printenv
può fare lo stessoenable
farlo anche con cmd.impostare variabile ma inutile a causa di alcune shell già può farlo senza env
, ad es
$ HOME = / dev HOME = / tmp USER = root / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env python
intestazione, ma comunque non portatile se env
non in / usr / bin
env -i
, disabilita tutto env. Ho trovato utile capire le variabili di ambiente critiche per determinati programmi per eseguirlo crontab
. es. [1] In modalità interattiva, esegui declare -p > /tmp/d.sh
per memorizzare le variabili degli attributi. [2] In /tmp/test.sh
, scrivi: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg
[3] Ora esegui env -i bash /tmp/test.sh
[4] Se riesce a visualizzare l'immagine, rimuovi metà delle variabili /tmp/d.sh
ed esegui di env -i bash /tmp/test.sh
nuovo. Se qualcosa non ha funzionato, annullalo. Ripetere il passaggio per restringere. [5] Alla fine ho capito che eog
bisogna $DISPLAY
correre crontab
, e in assenza di $DBUS_SESSION_BUS_ADDRESS
ciò rallenterà la visualizzazione dell'immagine.
target_PATH="$PATH:$(sudo printenv PATH)";
è utile per utilizzare direttamente il percorso di root senza dover analizzare ulteriormente l'output di env
o printenv
.
per esempio:
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:~$
Avendo un diverso punto di vista (da FreeBSD), hai:
Da 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.
Da 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.
Quindi questi comandi potrebbero avere lo stesso effetto senza argomenti, ma l' printenv
unico scopo è quello di visualizzare la chiave / i valori dell'ambiente corrente mentre l' env
obiettivo è di impostare un ambiente prima di chiamare un altro binario / script / qualunque cosa.
È più chiaro in questo modo?
Per saperne di più:
man 1 env
(FreeBSD)man 1 printenv
(FreeBSD)env
comando è apparso in 4.4BSD. Le opzioni -P, -S e -v sono state aggiunte in FreeBSD 6.0. Il printenv
comando è apparso in 3.0BSD. Quindi la ragione storica sembra essere quella printenv
arrivata per prima.
Dalle pagine man:
env - esegue un programma in un ambiente modificato
...
printenv - stampa tutto o parte dell'ambiente
Dovrebbe essere piuttosto esplicativo.
printenv
stampa solo tutte le variabili dell'ambiente corrente. Con env
te puoi preparare lo stesso ambiente con alcune modifiche se necessario ed eseguire un'app al suo interno.
ls
è un file binario, ma ll
è un alias comune, che di solito si espande ls -l
. printenv
e env
sono due binari diversi, non sono sicuro di quale sia stato introdotto per primo però. Puoi vedere altri esempi qui gnu.org/software/coreutils/manual/html_node/env-invocation.html
Parlando rigorosamente di funzionalità, env
è un file binario con una vasta gamma di funzionalità, una delle quali è la stampa di variabili d'ambiente, mentre printenv
stampa solo variabili d'ambiente.
Riassumendo, se sei abituato a lavorare con env, andrai avanti con env
la loro stampa (perché è quello a cui sei abituato) e se non lo sei, in genere ti ricorderai printenv
più velocemente.
Non ci sono praticamente differenze quando si parla di printenv
vs env
solo per la stampa di variabili ambientali. Ho appena controllato ed env è leggermente più pesante (circa 5 KB in più) e le loro prestazioni (nel tempo) sembrano essere esattamente le stesse.
Spero che questo lo chiarisca! :)
Se vuoi davvero sapere quanto è diverso l'output dei due binari indipendentemente dalla storia e dall'eredità di essi, puoi eseguire alcune utility per valutare questa differenza. Su debian ho eseguito alcune cose che saranno diverse a seconda di eventuali variabili ambientali personalizzate:
env |wc -l
printenv |wc -l
Entrambi i miei output hanno 41 righe
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Uscita: 41c41 <_ = / usr / bin / env ---
_ = / Usr / bin / printenv
Quindi vedi che c'è una linea diversa nelle due e quella linea è il numero 41 che immagino stabilisce il binario usato nel comando. Senza ulteriori argomenti, questi riportano informazioni identiche virtuali per me.