ความแตกต่างระหว่าง 'env' และ 'printenv' คืออะไร


67

ความแตกต่างระหว่างสองคำสั่งenvและprintenvคืออะไร? _พวกเขาทั้งสองแสดงตัวแปรสภาพแวดล้อมและการส่งออกจะตรงเดียวกันนอกเหนือจาก

มีเหตุผลทางประวัติศาสตร์หรือไม่ที่มีสองคำสั่งแทนที่จะเป็นหนึ่งคำสั่ง?

คำตอบ:


49

มีเหตุผลทางประวัติศาสตร์หรือไม่ที่มีสองคำสั่งแทนที่จะเป็นหนึ่งคำสั่ง?

มีลักษณะประวัติศาสตร์เพียง

  1. Bill Joy เขียนprintenvคำสั่งเวอร์ชันแรกในปี 1979 สำหรับ BSD
  2. UNIX System III เริ่มใช้envคำสั่งในปี 1980
  3. GNU ติดตาม UNIX System's envในปี 1986
  4. BSD ติดตาม GNU / UNIX System's envในปี 1988
  5. MINIX ติดตาม BSD printenvในปี 1988
  6. GNU ติดตาม MINX / BSD's printenvในปี 1989
  7. โปรแกรมอรรถประโยชน์การเขียนโปรแกรมเชลล์ของ GNU 1.0 รวมอยู่ในprintenvและenvในปี 1991
  8. GNU Shell Utilities ผสานเข้ากับ GNU coreutils ในปี 2002 ซึ่งเป็นสิ่งที่คุณพบได้ง่ายใน GNU / Linux ทุกวันนี้

โปรดทราบว่า "ติดตาม" ไม่ได้หมายความว่าซอร์สโค้ดเหมือนกันอาจเป็นไปได้ว่าพวกเขาจะถูกเขียนใหม่เพื่อหลีกเลี่ยงการฟ้องร้องดำเนินคดี

ดังนั้นสาเหตุที่คำสั่งทั้งสองนั้นมีอยู่เพราะเมื่อจอยเขียนprintenvตอนนั้นสิ่งที่envยังไม่เกิดขึ้น หลังจากการผสาน / ความเข้ากันได้เป็นเวลา 10 ปีและ GNU เจอแล้วตอนนี้คุณเห็นคำสั่งที่คล้ายกันทั้งสองที่หน้าเดียวกัน

ประวัตินี้ระบุไว้ดังต่อไปนี้: (ฉันพยายามที่จะลดคำตอบให้เหลือเพียง 2 ซอร์สโค้ดที่สำคัญที่นี่ส่วนที่เหลือคุณสามารถคลิกลิงค์ที่แนบมาเพื่อดู)

[ฤดูใบไม้ร่วงปี 2518]

เมื่อถึงฤดูใบไม้ร่วงปี 2518 นักศึกษาบัณฑิตสองคนที่ไม่มีใครสังเกตเห็นคือ Bill Joy และ Chuck Haley; พวกเขาทั้งสองสนใจในระบบใหม่ทันที เริ่มแรกพวกเขาเริ่มทำงานกับระบบปาสคาลที่ ธ อมป์สันแฮ็คด้วยกันขณะที่แขวนอยู่รอบ ๆ ห้องเครื่อง 11/70

[1977]

Joy เริ่มรวบรวม Berkeley Software Distribution (1BSD) ครั้งแรกซึ่งเปิดตัวเมื่อวันที่ 9 มีนาคม 2521 // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[กุมภาพันธ์, 1979]

2522 (ดู "บิลจอย UCB กุมภาพันธ์ 2522") / 2523 (ดู "ลิขสิทธิ์ [] ="), printenv.c // rf: http://minnie.tuhs.org/cgi-bin/utree.pl? ยื่น = 2.11BSD / src / เลือดจากสายสะดือ / 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]

ยากที่จะตรวจสอบเผยแพร่ใน 2BSD หรือ 3BSD // rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[มิถุนายน 1980]

UNIX รีลีส 3.0 หรือ "UNIX System 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]

BSD คู่มือแรก printenv // rf: http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man/man1/printenv.1 แต่ฉันไม่พบคู่มือที่เกี่ยวข้องกับ env ที่ใกล้เคียงที่สุดคือ getenv และ environ // http://minnie.tuhs.org/cgi-bin/utree.pl?file=2.11BSD/src/man

[1986]

รุ่นแรกของ GNU env// rf: ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/i386/1.0-RELEASE/ports/shellutils/src/env.c

[1987]

MINIX เปิดตัวครั้งแรก // rf: https://en.wikipedia.org/wiki/Andrew_S._Tanenbaum

  • Tanenbaum เขียน clone ของ UNIX ชื่อ MINIX (MINi-unIX) สำหรับพีซี IBM มันมุ่งเป้าไปที่นักเรียนและคนอื่น ๆ ที่ต้องการเรียนรู้วิธีการทำงานของระบบปฏิบัติการ

[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 ตุลาคม 2531]

MINIX เวอร์ชัน 1.3 // rf: https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI

... 32932 190 / minix/commands/printenv.c //printenv.c มีอยู่แล้ว

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

[1989]

รุ่นแรกของ GNU printenvอ้างถึง [12 สิงหาคม 1993]

[16 กรกฎาคม 1991]

"Shellutils" - โปรแกรมอรรถประโยชน์การเขียนโปรแกรมเชลล์ของ GNU 1.0 เปิดตัว // rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

โปรแกรมในแพ็คเกจนี้คือ:

basename date dirname envกลุ่ม expr id logname pathchk printenv printf sleep tee tty whoami ใช่ดี nohup stty uname

[12 สิงหาคม 2536]

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/ รุ่นที่

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

[1993]

printenv.c ซึ่งพบในซอร์สโค้ด DSLinux ในปี 2549 // rf: (Google) แคช: 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

[พฤศจิกายน 1993]

FreeBSD เวอร์ชันแรกเปิดตัวแล้ว // rf: https://en.wikipedia.org/wiki/FreeBSD

[กันยายน 1, 2002]

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

fileutils ของ GNU, textutils และ sh-utils (ดู "Shellutils" ที่ 16 กรกฎาคม 1991 ข้างบน) แพ็คเกจได้ถูกรวมเข้าเป็นหนึ่งเดียวเรียกว่า GNU coreutils

โดยรวมแล้วenvใช้กรณีเปรียบเทียบกับprintenv:

  1. ตัวแปรสภาพแวดล้อมการพิมพ์ แต่printenvสามารถทำเช่นเดียวกัน
  2. ปิดการใช้งานเชลล์ในตัว แต่สามารถทำได้ด้วยenablecmd ด้วย
  3. ตั้งค่าตัวแปร แต่ไม่มีจุดหมายเนื่องจากเชลล์บางตัวสามารถทำได้โดยไม่มีenvเช่น

    $ HOME = / dev HOME = / tmp USER = root / bin / bash -c "cd ~; pwd"

    tmp /

  4. #!/usr/bin/env pythonส่วนหัว แต่ยังไม่สามารถพกพาenvได้หากไม่อยู่ใน / usr / bin

  5. env -iปิดการใช้งาน env ทั้งหมด ฉันพบว่ามีประโยชน์ในการหาตัวแปรสภาพแวดล้อมที่สำคัญสำหรับบางโปรแกรมเพื่อให้ทำงานcrontabได้ เช่น [1] ในโหมดโต้ตอบให้เรียกใช้declare -p > /tmp/d.shเพื่อเก็บตัวแปรแอตทริบิวต์ [2] ใน/tmp/test.shเขียน: . /tmp/d.sh; eog /home/xiaobai/Pictures/1.jpg[3] ตอนนี้เรียกใช้env -i bash /tmp/test.sh[4] หากประสบความสำเร็จในการแสดงภาพให้ลบตัวแปรครึ่งหนึ่งใน/tmp/d.shแล้วเรียกใช้env -i bash /tmp/test.shอีกครั้ง หากสิ่งที่ล้มเหลวยกเลิกการทำมัน ทำซ้ำขั้นตอนนี้เพื่อ จำกัด ให้แคบลง [5] ในที่สุดฉันก็eogต้องออก$DISPLAYไปทำงานcrontabและถ้าขาดไป$DBUS_SESSION_BUS_ADDRESSจะทำให้การแสดงภาพช้าลง

  6. target_PATH="$PATH:$(sudo printenv PATH)";จะเป็นประโยชน์ต่อโดยตรงใช้เส้นทางรากโดยไม่ต้องเพิ่มเติมการแยกวิเคราะห์การส่งออกของหรือenvprintenv

เช่น:

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
บทเรียนประวัติศาสตร์ที่ดี
Ouki

21

มีมุมมองที่แตกต่าง (จาก FreeBSD) คุณมี:

จาก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.

จาก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.

ดังนั้นคำสั่งเหล่านี้อาจมีผลเหมือนกันโดยไม่มีการโต้แย้ง แต่printenvมีจุดประสงค์เพียงอย่างเดียวคือการแสดงคีย์ / ค่าของสภาพแวดล้อมปัจจุบันในขณะที่envตั้งเป้าหมายเพื่อตั้งค่าสภาพแวดล้อมบางอย่างก่อนที่จะเรียกไบนารี / สคริปต์ / อะไรก็ตาม

ชัดเจนขึ้นด้วยวิธีนี้หรือไม่

รู้จักมากขึ้น:


2
จากการเชื่อมโยงให้: คำสั่งที่ปรากฏใน 4.4BSD มีการเพิ่มตัวเลือก -P, -S และ -v ใน FreeBSD 6.0 คำสั่งที่ปรากฏใน 3.0BSD ดังนั้นเหตุผลทางประวัติศาสตร์ดูเหมือนว่าจะมาถึงก่อน env printenvprintenv
mcmlxxxvi


3

จากหน้าคน:

env - รันโปรแกรมในสภาพแวดล้อมที่ถูกปรับเปลี่ยน

...

printenv - พิมพ์ทั้งหมดหรือบางส่วนของสภาพแวดล้อม

ควรอธิบายให้สวย


4
แต่ฉันไม่ได้รับมัน ...
mikeserv

ฉันคิดว่า env มาก่อน printenv เหตุใดจึงต้องสร้างอีกไบนารี สิ่งนี้ไม่เหมือนกันกับสิ่งที่จะเป็น 'ls' เนื่องจาก 'll' ไม่ใช่ไบนารีและไม่มีหน้าคน
WiSaGaN

@mikeserv printenvเพียงพิมพ์ตัวแปรทั้งหมดของสภาพแวดล้อมปัจจุบัน ด้วยenvคุณสามารถเตรียมสภาพแวดล้อมเดียวกันกับการปรับเปลี่ยนบางอย่างถ้าจำเป็นและเรียกใช้แอปในนั้น
UVV

@WiSaGaN การเปรียบเทียบของคุณไม่ถูกต้องจริงๆ lsเป็นไบนารี แต่เป็นนามแฝงร่วมกันซึ่งมักจะเพียงแค่ขยายll และเป็นสองไบนารีที่แตกต่างกันฉันไม่แน่ใจว่าคนแรกที่ได้รับการแนะนำว่า คุณสามารถดูตัวอย่างเพิ่มเติมได้ที่นี่gnu.org/software/coreutils/manual/html_node/env-invocation.htmlls -lprintenvenv
UVV

1
@mikeserv ดูข้อความการวางเมาส์บนการ์ตูนนี้ :)
ไวด์การ์ด

3

พูดคุยเกี่ยวกับฟังก์ชันการทำงานอย่างเข้มงวดenvเป็นไบนารีที่มีชุดคุณลักษณะขนาดใหญ่หนึ่งในนั้นคือการพิมพ์ตัวแปรสภาพแวดล้อมในขณะที่printenvเพียงพิมพ์ตัวแปรสภาพแวดล้อม

โดยสรุปหากคุณคุ้นเคยกับการทำงานกับ env คุณจะได้ไปกับenvการพิมพ์พวกเขา (เพราะนั่นคือสิ่งที่คุณคุ้นเคย) และหากคุณไม่ได้ใช้คุณจะจำprintenvได้เร็วขึ้น

มีจริงไม่มีความแตกต่างเมื่อพูดถึงprintenvVS envเพียงพิมพ์ตัวแปรสิ่งแวดล้อม ฉันเพิ่งตรวจสอบและ env หนักกว่าเล็กน้อย (ประมาณ 5 KB เพิ่มเติม) และประสิทธิภาพ (ในเวลา) ดูเหมือนว่าจะเหมือนกันทุกประการ

หวังว่านี่จะเป็นการล้างออก! :)


-1

หากคุณต้องการทราบว่าเอาต์พุตของสองไบนารีที่ต่างกันโดยไม่คำนึงถึงประวัติและมรดกของมันนั้นเป็นอย่างไรคุณสามารถรันยูทิลิตี้บางอย่างเพื่อวัดความแตกต่างนี้ เดเบียนฉันวิ่งไปสองสามอย่างที่จะแตกต่างกันไปขึ้นอยู่กับสภาพแวดล้อมที่กำหนดเอง:

env |wc -l
printenv |wc -l

ทั้งเอาต์พุตของฉันมี 41 บรรทัด

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

เอาต์พุต: 41c41 <_ = / usr / bin / env ---

_ = / usr / bin / printenv

ดังนั้นคุณจะเห็นว่ามีหนึ่งบรรทัดที่แตกต่างกันในสองและบรรทัดนั้นคือหมายเลข 41 ซึ่งฉันเดากำหนดไบนารีที่ใช้ในคำสั่ง หากไม่มีข้อโต้แย้งเพิ่มเติมรายงานเหล่านี้จะเป็นข้อมูลเหมือนกันสำหรับฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.