「env」と「printenv」の違いは何ですか?

「env」と「printenv」の違いは何ですか?

env2つのコマンドの違いは何ですかprintenv?どちらも環境変数を表示し、それを除いて出力は同じです_

1つではなく2つのコマンドを使用する歴史的な理由はありますか?

答え1

1つではなく2つのコマンドを使用する歴史的な理由はありますか?

歴史がそうです。

歴史

  1. printenvBill Joyは1979年にBSDコマンドの最初のバージョンを作成しました。
  2. UNIX System IIIenvでは、1980年にコマンドを導入しました。
  3. GNUはUNIXシステムに続いて1986年に登場しましたenv
  4. BSDはGNU/UNIXシステムに続いて1988年に登場しましたenv
  5. MINIXは1988年にBSDの後に続きましたprintenv
  6. GNUは1989年にMINX / BSDの後に続きましたprintenv
  7. 1991 printenvGNUシェルプログラミングユーティリティ1.0が含まれています。env
  8. GNU Shell Utilitiesは2002年にGNU coreutilsにマージされ、これが今日GNU / Linuxで見られるものです。

「follow」は、ソースコードが同じであるという意味ではなく、ライセンス訴訟を避けるために書き直された可能性があります。

したがって、これら2つのコマンドは、Bill Joyが存在するprintenv前に作成したために存在しますenv。 10年間のマージ/互換性とGNUに会った後、同じページに2つの同様のコマンドを表示できるようになりました。

この記録は以下を示しています。 (回答を最小限に抑えようとしましたが、ここでは2つの基本的なソースコードの断片だけを提供しました。

[1975年秋]

1975年の秋には、目立たない2人の大学院生、ビル・ジョイ(Bill Joy)とチャック・ヘイリー(Chuck Haley)も到着しました。彼らはすべて新しい制度に即時の関心を示した。当初、彼らはThompsonが11月70日にコンピュータルームで遊んで一緒に解読したPascalシステムの仕事を始めました。

[1977]

Joyは1978年3月9日にリリースされた最初のBerkeley Software Distribution(1BSD)のコンパイルを開始しました。 //rf:https://en.wikipedia.org/wiki/Berkeley_Software_Distribution

[1979年2月]

1979("Bill Joy, UCB February, 1979"を参照)/1980("copyright[]="を参照)、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

[1980年6月]

UNIX バージョン 3.0 または "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マニュアル//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最初の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

[1988年10月4日]

MINIX バージョン 1.3 //rf:https://groups.google.com/forum/#!topic/comp.os.minix/cQ8kaiq1hgI

... 32932190 /minix/commands/printenv.c //printenv.c はすでに存在します。

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

[1989]

GNUの最初のバージョンprintenv、参照 [1993年8月12日]。

[1991年7月16日]

"Shellutils" - GNUシェルプログラミングユーティリティ1.0リリース//rf:https://groups.google.com/forum/#!topic/gnu.announce/xpTRtuFpNQc

このパッケージに含まれるプログラムは次のとおりです。

デフォルト名日付ディレクトリ名環境expr グループ ID ログ名パス chk印刷環境 printf sleep Tee tty whoami はい、いいね nohup stty uname

[1993年8月12日]

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

、GNUシェルユーティリティ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は2006年のDSLinuxソースコードで発見されました。 //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年11月]

FreeBSDの最初のバージョンがリリースされました。 //RF:https://en.wikipedia.org/wiki/FreeBSD

[2002年9月1日]

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. シェル組み込み機能を無効にしますが、enablecmdを使用して実装することもできます。

  3. 変数を設定しますが、一部のシェルではすでに変数なしで変数を設定できるため、意味がありませんenv

        $ HOME=/dev HOME=/tmp USER=root /bin/bash -c "cd ~; pwd"
    
            /tmp
    
    
  4. #!/usr/bin/env pythonenvヘッダーですが/usr/binにない場合は、まだ移植可能ではありません。

  5. env -i、すべての環境を無効にします。属性変数を保存するためにcrontabdeclare -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)";envまたは、出力をさらに解析せずに直接ルートパスを操作するのに役立ちます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:~$
    

答え2

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のバイナリ/スクリプト/何かを呼び出す前にいくつかの環境を設定することです。

これはもっと明確になりませんか?

もっと知りたいですか?

答え3

env POSIX 7ですprintenv いいえ(Ubuntu 15.10のGNU Coreutils)。

答え4

厳密に言えば、env多くの機能を備えたバイナリであり、その1つは環境変数を印刷し、printenv環境変数のみを印刷することです。

全体として、envの使用に精通している場合はenv印刷を続けます(なぜならこれは慣れているからです)。そうでなければ、一般的にprintenv早く覚えています。

printenv環境変数について話しているだけで印刷することにはenv実際に違いはありません。私はちょうど確認しましたが、envはやや重く(約5KB以上)、パフォーマンス(時間の経過)はまったく同じようです。

これが問題を解決することを願っています! :)

関連情報