Jawaban:
Apakah ada alasan historis mengapa ada dua perintah, bukan satu?
Hanya ada cara sejarah.
printenv
perintah pada tahun 1979 untuk BSD.env
perintah pada tahun 1980.env
pada tahun 1986.env
pada tahun 1988.printenv
pada tahun 1988.printenv
pada tahun 1989.printenv
dan env
pada tahun 1991.Perhatikan bahwa "diikuti" tidak berarti kode sumbernya sama, mungkin kode tersebut ditulis ulang untuk menghindari gugatan lisensi.
Jadi alasan mengapa kedua perintah itu ada adalah karena ketika Bill Joy menulis printenv
waktu itu, env
belum ada. Setelah 10 tahun penggabungan / kompatibilitas dan GNU menemukannya, Anda sekarang melihat kedua perintah serupa di halaman yang sama.
Riwayat ini ditunjukkan sebagai berikut: (Saya mencoba meminimalkan jawabannya dan hanya menyediakan 2 kode sumber penting di sini, sisanya Anda dapat mengklik tautan terlampir untuk melihat)
[musim gugur 1975]
Juga tiba pada musim gugur 1975 adalah dua mahasiswa pascasarjana yang tidak diketahui, Bill Joy dan Chuck Haley; mereka berdua segera tertarik pada sistem yang baru. Awalnya mereka mulai bekerja pada sistem Pascal yang telah diretas Thompson bersama sambil berkeliaran di ruang mesin 11/70.
[1977]
Joy mulai menyusun Berkeley Software Distribution (1BSD) pertama, yang dirilis pada 9 Maret 1978. // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
[Februari, 1979]
1979 (lihat "Bill Joy, UCB Februari, 1979") / 1980 (lihat "hak cipta [] ="), 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]
Sulit untuk menentukan dirilis dalam 2BSD ATAU 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution
3BSD Perintah printenv muncul di 3.0 BSD. // rf: http://www.freebsd.org/cgi/man.cgi?query=printenv&sektion=1#end 3.0 BSD diperkenalkan pada 1979 // rf: http://gunkies.org/wiki/3_BSD
2BSD Perintah printenv pertama kali muncul di 2BSD // rf: http://man.openbsd.org/printenv.1
[Juni, 1980]
UNIX Release 3.0 ATAU "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 printenv manual pertama // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 tetapi saya tidak dapat menemukan manual yang terkait dengan env , yang paling dekat adalah getenv dan environment // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man
[1986]
Versi pertama 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 dirilis // 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 versi 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI
... 32932 190 /minix/commands/printenv.c //printenv.c sudah ada
// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm
[1989]
Versi pertama GNU printenv
, lihat [12 Agustus 1993].
[16 Juli 1991]
"Shellutils" - Utilitas pemrograman shell GNU 1.0 dirilis // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc
Program-program dalam paket ini adalah:
basename date dirname env expr grup id logname pathchk printenv printf sleep tee tty whoami yes nice nohup stty uname
[12 Agustus 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 yang ditemukan pada kode sumber DSLinux pada tahun 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
[November 1993]
Versi pertama FreeBSD dirilis. // rf: https://en.wikipedia.org/wiki/FreeBSD
[1 september 2002]
http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils
Fileutils GNU, textutils, dan sh-utils (lihat "Shellutils" pada 16 Juli 1991 di atas) paket telah digabung menjadi satu, yang disebut GNU coreutils.
Secara keseluruhan, env
use case dibandingkan dengan printenv
:
printenv
dapat melakukan hal yang samaenable
cmd juga.atur variabel tetapi tidak berguna karena beberapa shell sudah dapat melakukannya tanpa env
, misalnya
$ HOME = / dev HOME = / tmp PENGGUNA = root / bin / bash -c "cd ~; pwd"
/ tmp
#!/usr/bin/env python
sundulan, tetapi tetap tidak portabel jika env
tidak di / usr / bin
env -i
, nonaktifkan semua env. Saya merasa berguna untuk mencari tahu variabel lingkungan kritis untuk program tertentu agar dapat dijalankan crontab
. misal [1] Dalam mode interaktif, jalankan declare -p > /tmp/d.sh
untuk menyimpan variabel atribut. [2] Dalam /tmp/test.sh
, tulis: . /tmp/d.sh;
eog /home/xiaobai/Pictures/1.jpg
[3] Sekarang jalankan env -i bash /tmp/test.sh
[4] Jika berhasil menampilkan gambar, hapus setengah dari variabel /tmp/d.sh
dan jalankan env -i bash /tmp/test.sh
lagi. Jika sesuatu gagal, urungkan. Ulangi langkah ini untuk mempersempit. [5] Akhirnya saya mencari tahu eog
membutuhkan $DISPLAY
untuk berjalan dalam crontab
, dan tidak ada dari $DBUS_SESSION_BUS_ADDRESS
akan memperlambat tampilan gambar.
target_PATH="$PATH:$(sudo printenv PATH)";
berguna untuk langsung menggunakan path root tanpa harus mem-parsing output env
atau printenv
.
misalnya:
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:~$
Memiliki sudut pandang yang berbeda (dari FreeBSD), Anda memiliki:
Dari 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.
Dari 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.
Jadi perintah-perintah ini mungkin memiliki efek yang sama tanpa argumen, tetapi printenv
satu-satunya tujuan adalah untuk menampilkan kunci / nilai lingkungan saat ini sementara env
mengarahkannya ke beberapa lingkungan sebelum memanggil biner / skrip lain / apa pun.
Apakah lebih jelas seperti ini?
Untuk lebih dikenal:
man 1 env
(FreeBSD)man 1 printenv
(FreeBSD)env
perintah muncul di 4.4BSD. Opsi -P, -S dan -v ditambahkan dalam FreeBSD 6.0. The printenv
perintah muncul di 3.0BSD. Jadi alasan historis tampaknya yang printenv
datang lebih dulu.
env
adalah POSIX 7 ,printenv
bukan (GNU Coreutils di Ubuntu 15.10).
Dari halaman manual:
env - menjalankan program dalam lingkungan yang dimodifikasi
...
printenv - cetak semua atau sebagian lingkungan
Seharusnya cukup jelas.
printenv
hanya mencetak semua variabel lingkungan saat ini. Dengan env
Anda dapat menyiapkan lingkungan yang sama dengan beberapa modifikasi jika perlu dan menjalankan aplikasi di dalamnya.
ls
adalah biner, tetapi ll
merupakan alias umum, yang biasanya hanya diperluas ke ls -l
. printenv
dan env
dua binari yang berbeda, saya tidak yakin mana yang pertama kali diperkenalkan. Anda dapat melihat beberapa contoh lagi di sini gnu.org/software/coreutils/manual/html_node/env-invocation.html
Berbicara tentang fungsionalitas, env
adalah biner dengan serangkaian fitur yang besar, salah satunya adalah variabel lingkungan pencetakan, sedangkan printenv
hanya mencetak variabel lingkungan.
Ringkasnya, jika Anda terbiasa bekerja dengan env, Anda akan menggunakannya env
untuk mencetaknya (karena itulah yang biasa Anda lakukan) dan jika tidak, Anda biasanya akan mengingat printenv
lebih cepat.
Praktis tidak ada perbedaan ketika berbicara tentang printenv
vs env
hanya untuk mencetak variabel lingkungan. Saya baru saja memeriksa dan ENV sedikit lebih berat (sekitar 5 KB ekstra), dan kinerja mereka (dalam waktu) tampaknya persis sama.
Semoga ini jelas! :)
Jika Anda benar-benar ingin tahu bagaimana perbedaan keluaran dari dua binari terlepas dari sejarah dan warisan mereka, Anda dapat menjalankan beberapa utilitas untuk mengukur perbedaan ini. Pada debian saya menjalankan beberapa hal yang akan berbeda tergantung pada vars lingkungan kustom:
env |wc -l
printenv |wc -l
Kedua output saya memiliki 41 baris
env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt
Output: 41c41 <_ = / usr / bin / env ---
_ = / usr / bin / printenv
Jadi Anda melihat ada satu baris yang berbeda dalam dua dan baris itu adalah nomor 41 yang saya kira menetapkan biner yang digunakan dalam perintah. Tanpa argumen tambahan, ini melaporkan info identik virtual untuk saya.