Antworten:
Gibt es historische Gründe dafür, dass es zwei anstelle von einem Befehl gibt?
Es gab nur Geschichte.
printenv
1979 die erste Version des Befehls für BSD.env
Befehl 1980 ein.env
1986 den UNIX-Systemen .env
1988 GNU / UNIX-Systemen .printenv
1988 BSD .printenv
im Jahr 1989.printenv
und env
im Jahr 1991.Beachten Sie, dass "gefolgt" nicht bedeutet, dass der Quellcode derselbe ist. Wahrscheinlich wurden sie umgeschrieben, um Lizenzstreitigkeiten zu vermeiden.
Der Grund, warum beide Befehle existierten, ist, printenv
dass sie env
noch nicht existierten, als Bill Joy diese Zeit schrieb . Nach 10 Jahren Merging / Compatibility und GNU sehen Sie nun beide ähnlichen Befehle auf derselben Seite.
Dieser Verlauf zeigt Folgendes an: (Ich versuche, die Antwort zu minimieren und biete hier nur zwei wichtige Quellcodes an. Den Rest können Sie durch Klicken auf die angehängten Links sehen.)
[Herbst 1975]
Ebenfalls im Herbst 1975 trafen zwei unbemerkte Doktoranden ein, Bill Joy und Chuck Haley; Beide interessierten sich sofort für das neue System. Zunächst arbeiteten sie an einem Pascal-System, das Thompson zusammen gehackt hatte, als er im Maschinenraum 11/70 herumlungerte.
[1977]
Joy begann die erste Berkeley Software Distribution (1BSD) kompilieren, die am 9. März veröffentlicht wurde, 1978 // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Februar 1979]
1979 (siehe "Bill Joy, UCB February 1979") / 1980 (siehe "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]
Schwer zu bestimmen, veröffentlicht in 2BSD ODER 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD Der Befehl printenv wurde in 3.0 BSD angezeigt. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD wurde 1979 eingeführt // rf: http://gunkies.org/wiki/3_BSD
2BSD Der Befehl printenv ist erstmals in 2BSD // rf: http://man.openbsd.org/printenv.1 enthalten
[Juni 1980]
UNIX Release 3.0 ODER "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-Handbuch für den ersten Druck // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1, aber ich kann kein Handbuch zu env finden Am nächsten ist getenv und environ // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Erste Version von 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 veröffentlicht // 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. Oktober 1988]
MINIX Version 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c existiert bereits
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Erste Version von GNU printenv
, siehe [12. August 1993].
[16. Juli 1991]
"Shellutils" - GNU Shell Programming Utilities 1.0 veröffentlicht // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Die Programme in diesem Paket sind:
basename date dirname env expr gruppen id logname pathchk printenv printf sleep tty whoami yes nice nohup stty uname
[12. August 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, das 2006 im DSLinux-Quellcode gefunden wurde. html
--- NEW FILE: printenv.c ---
/*
* Copyright (c) 1993 by David I. Bell
[November 1993]
Die erste Version von FreeBSD wurde veröffentlicht. // rf: https://en.wikipedia.org/wiki/FreeBSD
[1. September 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
Die GNU-Pakete fileutils, textutils und sh-utils (siehe "Shellutils" am 16. Juli 1991 oben) wurden in einem einzigen Paket zusammengeführt, das als GNU-Coreutils bezeichnet wird.
Insgesamt env
vergleichen Use Cases mit printenv
:
printenv
können aber das Gleiche tunenable
.variabel aber sinnlos eingestellt aufgrund mancher schalen kann man es schon ohne env
zb
$ HOME = / dev HOME = / tmp USER = root / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env python
Header, aber immer noch nicht portierbar, wenn env
nicht in / usr / bin
env -i
, deaktiviere alle env. Ich fand es nützlich, die kritischen Umgebungsvariablen für ein bestimmtes Programm herauszufinden, damit es ausgeführt werden kann crontab
. zB [1] Im interaktiven Modus ausführen, declare -p > /tmp/d.sh
um Attributvariablen zu speichern. [2] /tmp/test.sh
Schreiben Sie in: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg
[3] Führen Sie nun env -i bash /tmp/test.sh
[4] aus. Wenn das Anzeigen des Bildes erfolgreich ist, entfernen Sie die Hälfte der Variablen in /tmp/d.sh
und führen Sie es env -i bash /tmp/test.sh
erneut aus. Wenn etwas fehlgeschlagen ist, machen Sie es rückgängig. Wiederholen Sie den Schritt, um ihn einzugrenzen. [5] Schließlich finde ich heraus, dass es eog
erforderlich ist $DISPLAY
, hineinzulaufen crontab
, und mangels $DBUS_SESSION_BUS_ADDRESS
Willens wird die Anzeige des Bildes verlangsamt.
target_PATH="$PATH:$(sudo printenv PATH)";
ist nützlich, um den Root-Pfad direkt zu verwenden, ohne die Ausgabe von env
oder weiter analysieren zu müssen printenv
.
z.B:
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:~$
Mit einer anderen Sichtweise (von FreeBSD aus) haben Sie:
Von 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.
Von 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.
Daher haben diese Befehle möglicherweise den gleichen Effekt ohne Argument, aber der printenv
einzige Zweck besteht darin, die aktuellen Umgebungsschlüssel / -werte anzuzeigen env
und gleichzeitig eine Umgebung festzulegen, bevor eine andere Binärdatei / ein anderes Skript / was auch immer aufgerufen wird.
Ist das so klarer?
Um mehr zu wissen:
man 1 env
(FreeBSD)man 1 printenv
(FreeBSD)env
Befehl wurde in 4.4BSD angezeigt. Die Optionen -P, -S und -v wurden in FreeBSD 6.0 hinzugefügt. Der printenv
Befehl erschien in 3.0BSD. Der historische Grund scheint also der printenv
zuerst angekommene zu sein.
env
ist POSIX 7 ,printenv
ist nicht (GNU Coreutils in Ubuntu 15.10).
Aus Manpages:
Führen Sie ein Programm in einer geänderten Umgebung aus
...
printenv - druckt die gesamte Umgebung oder einen Teil davon
Sollte ziemlich erklärend sein.
printenv
druckt nur alle Variablen der aktuellen Umgebung. Mit können env
Sie bei Bedarf die gleiche Umgebung mit einigen Änderungen vorbereiten und eine App darin ausführen.
ls
ist eine Binärdatei, ist aber ll
ein allgemeiner Alias, der normalerweise nur erweitert wird ls -l
. printenv
und es env
gibt zwei verschiedene Binärdateien, ich bin mir nicht sicher, welche zuerst eingeführt wurde. Weitere Beispiele finden Sie hier: gnu.org/software/coreutils/manual/html_node/env-invocation.html
Genau genommen env
handelt es sich um eine Binärdatei mit einer Vielzahl von Funktionen, von denen eine Umgebungsvariablen printenv
druckt , während nur Umgebungsvariablen gedruckt werden.
Zusammenfassend lässt sich sagen, dass Sie, wenn Sie an die Arbeit mit env gewöhnt sind, env
diese drucken müssen (weil Sie das gewohnt sind). Andernfalls werden Sie sich in der Regel printenv
schneller daran erinnern .
Es gibt praktisch keine Unterschiede, wenn es um printenv
vs geht, env
nur um das Drucken von Umgebungsvariablen. Ich habe gerade nachgesehen, und env ist etwas schwerer (ca. 5 zusätzliche KB), und die Leistung (mit der Zeit) scheint genau gleich zu sein.
Hoffe das klärt es aus! :)
Wenn Sie wirklich wissen möchten, wie unterschiedlich die Ausgabe der beiden Binärdateien ist, unabhängig vom Verlauf und dem Erbe der beiden Binärdateien, können Sie einige Dienstprogramme ausführen, um diesen Unterschied zu messen. Unter Debian habe ich einige Dinge ausgeführt, die je nach benutzerdefinierten Umgebungsvariablen unterschiedlich sein werden:
env |wc -l
printenv |wc -l
Beide meine Ausgabe hat 41 Zeilen
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Ausgabe: 41c41 <_ = / usr / bin / env ---
_ = / usr / bin / printenv
Sie sehen also, dass es in den beiden eine andere Zeile gibt und diese Zeile die Nummer 41 ist, in der die im Befehl verwendete Binärdatei festgelegt ist. Ohne zusätzliche Argumente melden diese für mich nahezu identische Informationen.