Sự khác biệt giữa 'env' và 'printenv' là gì?


67

Sự khác biệt giữa hai lệnh envvà là printenvgì? Cả hai đều hiển thị các biến môi trường và đầu ra hoàn toàn giống nhau _.

Có bất kỳ lý do lịch sử cho việc có hai lệnh thay vì một?

Câu trả lời:


49

Có bất kỳ lý do lịch sử cho việc có hai lệnh thay vì một?

Có cách lịch sử.

  1. Bill Joy đã viết phiên bản đầu tiên của printenvlệnh vào năm 1979 cho BSD.
  2. UNIX System III giới thiệu envlệnh vào năm 1980.
  3. GNU đã theo hệ thống UNIX envvào năm 1986.
  4. BSD đã theo hệ thống GNU / UNIX envvào năm 1988.
  5. MINIX theo BSD printenvnăm 1988.
  6. GNU đã theo dõi MINX / BSD printenvvào năm 1989.
  7. Các tiện ích lập trình shell GNU 1.0 được bao gồm printenvenvvào năm 1991.
  8. GNU Shell Utility đã hợp nhất vào GNU coreutils vào năm 2002, đó là những gì bạn có thể dễ dàng tìm thấy trong GNU / Linux ngày nay.

Lưu ý rằng "theo sau" không có nghĩa là mã nguồn giống nhau, có thể chúng được viết lại để tránh kiện cáo giấy phép.

Vì vậy, lý do tại sao cả hai lệnh tồn tại là vì khi Bill Joy viết printenvvào thời điểm đó, envnó vẫn chưa tồn tại. Sau 10 năm hợp nhất / tương thích và GNU đi qua nó, bây giờ bạn đang thấy cả hai lệnh tương tự trên cùng một trang.

Lịch sử này được chỉ ra như sau: (Tôi cố gắng thu nhỏ câu trả lời và do đó chỉ cung cấp 2 mã nguồn thiết yếu ở đây, phần còn lại bạn có thể nhấp vào các liên kết đính kèm để xem)

[mùa thu năm 1975]

Cũng đến mùa thu năm 1975 là hai sinh viên tốt nghiệp không được chú ý là Bill Joy và Chuck Haley; cả hai đều quan tâm ngay lập tức đến hệ thống mới. Ban đầu, họ bắt đầu làm việc trên một hệ thống Pascal mà Thompson đã hack cùng nhau trong khi treo xung quanh phòng máy 11/70.

[1977]

Joy bắt đầu biên dịch Bản phân phối phần mềm Berkeley (1BSD) đầu tiên, được phát hành vào ngày 9 tháng 3 năm 1978. // rf: https://en.wikipedia.org/wiki/Ber siêu_Software_Distribution

[Tháng Hai, 1979]

1979 (xem "Bill Joy, UCB tháng 2 năm 1979") / 1980 (xem "bản quyền [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? tệp = 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]

Khó xác định được phát hành trong 2BSD HOẶC 3BSD // rf: https://en.wikipedia.org/wiki/Ber siêu_Software_Distribution

[Tháng Sáu, 1980]

UNIX Release 3.0 HOẶC "Hệ thống UNIX III" // rf: ftp://pdp11.org.ru/pub/unix-archive/PDP-11/Distribution/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]

Hướng dẫn sử dụng printenv đầu tiên của BSD // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 nhưng tôi không thể tìm thấy hướng dẫn liên quan đến env , gần nhất là getenv và môi trường // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man

[1986]

Phiên bản đầu tiên của GNU env// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-release/i386/1.0-RELEASE/ports/shellutils/src/env.c

[1987]

MINIX đầu tiên được phát hành // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum đã viết một bản sao của UNIX, được gọi là MINIX (MINi-unIX), cho PC của IBM. Nó được nhắm mục tiêu vào các sinh viên và những người khác muốn tìm hiểu làm thế nào một hệ điều hành làm việc.

[1988]

Bv 1 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 tháng 10 năm 1988]

Phiên bản MINIX 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI

... 32932 190 /minix/commands/printenv.c //printenv.c đã tồn tại

// rf: http://www.informatica.co.cr/linux/research/1990/0202.htm

[1989]

Phiên bản đầu tiên của GNU printenv, tham khảo [12 tháng 8 năm 1993].

[16 tháng 7 năm 1991]

"Shellutils" - Các tiện ích lập trình shell GNU 1.0 được phát hành // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

Các chương trình trong gói này là:

tên cơ sở ngày dirname env expr nhóm id logname pathchk printenv printf ngủ tee tty whoami yes đẹp nohup stty uname

[12 tháng 8 năm 1993]

printenv.c // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-release/i386/1.0-RELEASE/ports/shellutils/src/printenv.c

, GNU Shell Utility 1.8 // rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-release/i386/1.0-RELEASE/ports/shellutils/VERSION

/* printenv -- print all or part of environment
   Copyright (C) 1989, 1991 Free Software Foundation.
...

[1993]

printenv.c được tìm thấy trên mã nguồn DSLinux năm 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

[Tháng 11 năm 1993]

Phiên bản đầu tiên của FreeBSD đã được phát hành. // rf: https://en.wikipedia.org/wiki/FreeBSD

[tháng 1 năm 2002]

http://git.savannah.gnu.org/cgit/coreutils.git/tree/README-package-renamed-to-coreutils

Các tập tin GNU, textutils và sh-utils (xem "Shellutils" vào ngày 16 tháng 7 năm 1991 ở trên) đã được hợp nhất thành một, được gọi là các lõi GNU.

Nhìn chung, envcác trường hợp sử dụng so với printenv:

  1. in các biến môi trường, nhưng printenvcó thể làm tương tự
  2. Vô hiệu hóa shell dựng sẵn nhưng cũng có thể đạt được với enablecmd.
  3. thiết lập biến nhưng vô nghĩa do một số shell đã có thể làm điều đó mà không có env, ví dụ

    $ HOME = / dev HOME = / tmp NGƯỜI DÙNG = root / bin / bash -c "cd ~; pwd"

    / tmp

  4. #!/usr/bin/env pythontiêu đề, nhưng vẫn không thể di động nếu envkhông trong / usr / bin

  5. env -i, vô hiệu hóa tất cả env. Tôi thấy nó hữu ích để tìm ra các biến môi trường quan trọng cho chương trình nhất định để làm cho nó chạy từ đó crontab. ví dụ [1] Trong chế độ tương tác, chạy declare -p > /tmp/d.shđể lưu trữ các biến thuộc tính. [2] In /tmp/test.sh, write: . /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg[3] Bây giờ chạy env -i bash /tmp/test.sh[4] Nếu thành công để hiển thị hình ảnh, hãy loại bỏ một nửa biến trong /tmp/d.shvà chạy env -i bash /tmp/test.shlại. Nếu một cái gì đó thất bại, hoàn tác nó. Lặp lại bước để thu hẹp. [5] Cuối cùng tôi nhận ra eogcần $DISPLAYphải chạy vào crontab, và vắng mặt $DBUS_SESSION_BUS_ADDRESSsẽ làm chậm việc hiển thị hình ảnh.

  6. target_PATH="$PATH:$(sudo printenv PATH)";là hữu ích để sử dụng trực tiếp đường dẫn gốc mà không cần phải phân tích cú pháp đầu ra của envhoặc printenv.

ví dụ:

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:~$

4
Bài học lịch sử tốt đẹp.
Ouki

21

Có quan điểm khác (từ FreeBSD), bạn có:

Từ 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.

Từ 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.

Vì vậy, các lệnh này có thể có tác dụng tương tự mà không cần đối số, nhưng printenvmục đích duy nhất là hiển thị khóa / giá trị môi trường hiện tại trong khi envmục tiêu là đặt một số môi trường trước khi gọi một nhị phân / script / bất cứ thứ gì.

Có phải rõ ràng hơn theo cách này?

Để biết thêm:


2
Từ các liên kết được cung cấp: Các envlệnh xuất hiện trong 4.4BSD. Các tùy chọn -P, -S và -v đã được thêm vào FreeBSD 6.0. Các printenvlệnh xuất hiện trong 3.0BSD. Vì vậy, lý do lịch sử dường như là printenvđến đầu tiên.
mcmlxxxvi


3

Từ trang con người:

env - chạy chương trình trong môi trường đã sửa đổi

...

printenv - in tất cả hoặc một phần của môi trường

Nên được giải thích khá.


4
nhưng tôi không hiểu được ...
mikeerv

Tôi cho rằng env đến trước printenv. Vậy tại sao làm một nhị phân khác? Điều này không giống với những gì 'sẽ' thành 'ls' vì 'll' không phải là trang nhị phân và không có trang man.
WiSaGaN

@mikeerv printenvchỉ in tất cả các biến của môi trường hiện tại. Với envbạn có thể chuẩn bị môi trường tương tự với một số sửa đổi nếu cần thiết và chạy một ứng dụng trong đó.
UVV

@WiSaGaN so sánh của bạn không thực sự chính xác. lslà một nhị phân, nhưng lllà một bí danh phổ biến, thường chỉ mở rộng ra ls -l. printenvenvlà hai nhị phân khác nhau, tôi không chắc cái nào được giới thiệu trước. Bạn có thể xem thêm một số ví dụ tại đây gnu.org/software/coreutils/manual/html_node/env-invocation.html
UVV

1
@mikeerv, xem văn bản di chuột trên truyện tranh này . :)
tự đại diện

3

Nói một cách nghiêm túc về các chức năng, envlà một hệ nhị phân với một bộ tính năng khổng lồ, một trong số đó là in các biến môi trường, trong khi printenvchỉ in các biến môi trường.

Tóm tắt, nếu bạn đã quen làm việc với env, bạn sẽ đi cùng envđể in chúng (vì đó là những gì bạn đã quen) và nếu bạn không, bạn thường sẽ nhớ printenvnhanh hơn.

Thực tế không có sự khác biệt khi nói về printenvvs envchỉ in các biến môi trường. Tôi mới kiểm tra và env nặng hơn một chút (khoảng 5 KB thêm) và hiệu suất của chúng (theo thời gian) dường như giống hệt nhau.

Hy vọng điều này sẽ xóa nó ra! :)


-1

Nếu bạn thực sự muốn biết đầu ra của hai nhị phân khác nhau như thế nào bất kể lịch sử và di sản của chúng, bạn có thể chạy một vài tiện ích để đánh giá sự khác biệt này. Trên debian tôi đã chạy một vài thứ sẽ khác nhau tùy thuộc vào bất kỳ lọ môi trường tùy chỉnh nào:

env |wc -l
printenv |wc -l

Cả hai đầu ra của tôi có 41 dòng

env > env.txt
printenv > printenv.txt
diff env.txt printenv.txt

Đầu ra: 41c41 <_ = / usr / bin / env ---

_ = / usr / bin / printenv

Vì vậy, bạn thấy có một dòng khác nhau trong hai và dòng đó là số 41 mà tôi đoán quy định nhị phân được sử dụng trong lệnh. Không có đối số bổ sung, những báo cáo thông tin giống hệt ảo cho tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.