Environment-Variables

“env”和“printenv”有什麼區別?

  • January 21, 2021

env這兩個命令和有什麼區別printenv?它們都顯示環境變數,除了_.

有兩個命令而不是一個命令是否有任何歷史原因?

有兩個命令而不是一個命令是否有任何歷史原因?

有,只是歷史的方式。

  1. printenvBill Joy於 1979 年為 BSD編寫了第一個版本的命令。
  2. UNIX System IIIenv在 1980 年引入了命令。
  3. GNUenv在 1986 年緊隨 UNIX 系統。
  4. BSDenv在 1988 年緊隨 GNU/UNIX 系統。
  5. MINIXprintenv在 1988 年緊隨 BSD。
  6. GNU 在 1989 年緊隨 MINX/BSD printenv
  7. GNU shell 程式實用程序 1.0 包括在 1991 年printenvenv
  8. GNU Shell Utilities 於 2002 年合併到 GNU coreutils,這就是你現在在 GNU/Linux 中找到的。

請注意,“followed”並不意味著原始碼相同,可能它們被重寫以避免許可訴訟。

所以,這兩個命令存在的原因是因為比爾喬伊printenv甚至在env存在之前就寫了。經過 10 年的合併/兼容性和 GNU 遇到它,您現在可以在同一頁面上看到兩個相似的命令。

這段歷史表明如下:( 我試圖最小化答案,在這裡只提供了2個基本的原始碼片段。其餘的你可以點擊附加的連結查看更多)

$$ fall of 1975 $$

同樣在 1975 年秋天抵達的還有兩名未被注意到的研究生,比爾·喬伊和查克·黑利。他們都對新系統產生了直接的興趣。最初,他們開始研究湯普森在 11/70 機房附近閒逛時一起破解的 Pascal 系統。

$$ 1977 $$

Joy 開始編譯第一個伯克利軟體發行版 (1BSD),該發行版於 1978 年 3 月 9 日發布。 //rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

$$ February, 1979 $$

1979(參見“Bill Joy,UCB,1979 年 2 月”)/1980(參見“版權

$$ $$=") , 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 $$

很難確定在 2BSD 或 3BSD 中發布 //rf: https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

$$ June, 1980 $$

UNIX 版本 3.0 或“UNIX 系統 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 &lt; 1.4"
/*
*      env [ - ] [ name=value ]... [command arg...]
*      set environment, then execute command (or print environment)
*      - says start fresh, otherwise merge with inherited environment
*/
#include &lt;stdio.h&gt;

#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 &lt; &newenv[NENV-1]; p++)
               if (nvmatch(arg, *p) != NULL) {
                       *p = arg;
                       return;
               }
       if (p &gt;= &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 為 IBM PC 編寫了一個名為 MINIX (MINI-uniX) 的 UNIX 複製。它針對想要了解作業系統如何工作的學生和其他人。

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

$$ October 4, 1988 $$

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,參考

$$ August 12, 1993 $$. $$ July 16, 1991 $$

“Shellutils” - GNU shell 程式實用程序 1.0 發布 //rf: https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

該軟體包中的程序是:

basename date dirname env expr groups id logname pathchk printenv printf sleep tee tty whoami 是 nice nohup stty uname

$$ August 12, 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 實用程序 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 $$

2006 年在 DSLinux 原始碼中找到的 printenv.c //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 $$

FreeBSD 的第一個版本發布。//rf: https://en.wikipedia.org/wiki/FreeBSD

$$ september 1, 2002 $$

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

GNU fileutils、textutils 和 sh-utils(參見上文 1991 年 7 月 16 日的“Shellutils”)包已合併為一個,稱為 GNU coreutils。

總體而言,env案例與printenv

  1. 列印環境變數,但printenv也可以這樣做
  2. 禁用 shell 內置,但也可以使用enablecmd 實現。
  3. 設置變數但沒有意義,因為某些 shell 已經可以在沒有 的情況下做到這一點env,例如

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

/tmp 4. #!/usr/bin/env python``env標頭,但如果不在 /usr/bin 中,仍然不可移植 5. env -i,禁用所有環境。我發現找出某個程序的關鍵環境變數以使其從crontab. 例如

$$ 1 $$在互動模式下,執行declare -p &gt; /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.shenv -i bash /tmp/test.sh再次執行。如果某件事失敗,請撤消它。重複該步驟以縮小範圍。$$ 5 $$最後我發現eog需要$DISPLAY執行crontab,並且不存在$DBUS_SESSION_BUS_ADDRESS會減慢圖像的顯示速度。 6. target_PATH="$PATH:$(sudo printenv PATH)";直接使用根路徑而不需要進一步解析envor的輸出很有用printenv

例如:

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

引用自:https://unix.stackexchange.com/questions/123473