Apa perbedaan antara 'env' dan 'printenv'?

67

Apa perbedaan antara kedua perintah envdan printenv? Mereka berdua menunjukkan variabel lingkungan, dan output persis sama selain _.

Apakah ada alasan historis mengapa ada dua perintah, bukan satu?

WiSaGaN
sumber

Jawaban:

49

Apakah ada alasan historis mengapa ada dua perintah, bukan satu?

Hanya ada cara sejarah.

  1. Bill Joy menulis versi pertama printenvperintah pada tahun 1979 untuk BSD.
  2. Sistem UNIX III memperkenalkan envperintah pada tahun 1980.
  3. GNU mengikuti Sistem UNIX envpada tahun 1986.
  4. BSD mengikuti Sistem GNU / UNIX envpada tahun 1988.
  5. MINIX mengikuti BSD printenvpada tahun 1988.
  6. GNU mengikuti MINX / BSD printenvpada tahun 1989.
  7. Utilitas pemrograman shell GNU 1.0 disertakan printenvdan envpada tahun 1991.
  8. GNU Shell Utilities bergabung ke GNU coreutils pada tahun 2002, yang merupakan apa yang dapat Anda temukan dengan mudah di GNU / Linux saat ini.

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 printenvwaktu itu, envbelum 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

[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

  • Tanenbaum menulis tiruan dari UNIX, yang disebut MINIX (MINi-unIX), untuk PC IBM. Itu ditargetkan pada siswa dan orang lain yang ingin belajar bagaimana sistem operasi bekerja.

[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, envuse case dibandingkan dengan printenv:

  1. mencetak variabel lingkungan, tetapi printenvdapat melakukan hal yang sama
  2. Nonaktifkan shell builtin tetapi dapat melakukannya dengan enablecmd juga.
  3. 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

  4. #!/usr/bin/env pythonsundulan, tetapi tetap tidak portabel jika envtidak di / usr / bin

  5. 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.shuntuk 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.shdan jalankan env -i bash /tmp/test.shlagi. Jika sesuatu gagal, urungkan. Ulangi langkah ini untuk mempersempit. [5] Akhirnya saya mencari tahu eogmembutuhkan $DISPLAYuntuk berjalan dalam crontab, dan tidak ada dari $DBUS_SESSION_BUS_ADDRESSakan memperlambat tampilan gambar.

  6. target_PATH="$PATH:$(sudo printenv PATH)";berguna untuk langsung menggunakan path root tanpa harus mem-parsing output envatau 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:~$
林果 皞
sumber
4
Pelajaran sejarah yang bagus.
Ouki
21

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 printenvsatu-satunya tujuan adalah untuk menampilkan kunci / nilai lingkungan saat ini sementara envmengarahkannya ke beberapa lingkungan sebelum memanggil biner / skrip lain / apa pun.

Apakah lebih jelas seperti ini?

Untuk lebih dikenal:

Ouki
sumber
2
Dari link yang disediakan: The envperintah muncul di 4.4BSD. Opsi -P, -S dan -v ditambahkan dalam FreeBSD 6.0. The printenvperintah muncul di 3.0BSD. Jadi alasan historis tampaknya yang printenvdatang lebih dulu.
mcmlxxxvi
5

env adalah POSIX 7 ,printenv bukan (GNU Coreutils di Ubuntu 15.10).

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber
3

Dari halaman manual:

env - menjalankan program dalam lingkungan yang dimodifikasi

...

printenv - cetak semua atau sebagian lingkungan

Seharusnya cukup jelas.

UVV
sumber
4
tetapi saya tidak mengerti ...
mikeserv
Saya kira env datang sebelum printenv. Jadi mengapa membuat biner lain? Ini tidak sama dengan apa yang akan 'menjadi' ls 'karena' ll 'bukan biner dan tidak memiliki halaman manual.
WiSaGaN
@ mikeserv printenvhanya mencetak semua variabel lingkungan saat ini. Dengan envAnda dapat menyiapkan lingkungan yang sama dengan beberapa modifikasi jika perlu dan menjalankan aplikasi di dalamnya.
UVV
@WiSaGaN perbandingan Anda tidak benar. lsadalah biner, tetapi llmerupakan alias umum, yang biasanya hanya diperluas ke ls -l. printenvdan envdua 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
UVV
1
@ mikeserv, lihat teks mouseover di komik ini . :)
Wildcard
3

Berbicara tentang fungsionalitas, envadalah biner dengan serangkaian fitur yang besar, salah satunya adalah variabel lingkungan pencetakan, sedangkan printenvhanya mencetak variabel lingkungan.

Ringkasnya, jika Anda terbiasa bekerja dengan env, Anda akan menggunakannya envuntuk mencetaknya (karena itulah yang biasa Anda lakukan) dan jika tidak, Anda biasanya akan mengingat printenvlebih cepat.

Praktis tidak ada perbedaan ketika berbicara tentang printenvvs envhanya 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! :)

David González Ruiz
sumber
-1

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.

pemburu
sumber