私はGDMでUbuntu 18.04を使用しています。私の.bashrcファイルからいくつかのbash機能をエクスポートしようとしています.profile
。
説明したようにこれはとても良い素材です.bashrc
、の主な違いは、.profile
後者がログインシェルでのみ実行されることです。
.profile
私はエクスポートを使用してに合わないものを得ることに成功しました。したがって、グラフィカルログインシェルでもその情報を正常に取得できることが.bashrc
わかります。.profile
たとえば、私の$PATH
定義は次のようになります。
export PATH="something/bin:$PATH"
.bashrc
これを に入れると、"something/bin"
サブシェルを実行するたびに再挿入されます。
$ echo $PATH
something/bin:/usr/local/bin:/usr/bin:/bin
$ bash
$ echo $PATH
something/bin:something/bin:/usr/local/bin:/usr/bin:/bin
しかし、このような関数をエクスポートすると、グラフィカルログインでは機能しないようです。
hello () { echo "hello"; }
export -f hello
bash -l
ログインしてもコンソールからログインしても、うまく機能します。
したがって、質問は次のようになります。.profile
ソースが明らかに得られた場合(環境変数が正常にエクスポートされ、明示的にソースがあるとマークされている場合/etc/gdm3/Xsession
)、エクスポートされた関数が機能しないのはなぜですか?
ベストアンサー1
これは、「で説明されている問題の特定のケースである可能性が高いです。私のBASH_FUNC_foobar%%環境変数がシェルサブプロセスに設定されていないのはなぜですか?」。
から関数をエクスポートすると、bash
特別な名前を持つ環境変数が生成されます。
$ foo () { echo hello; }
$ export -f foo
$ env
...
BASH_FUNC_foo%%=() { echo hello
}
...
シェルは、シェル関数がこれを実行できないため、これを行います。本物次へエクスポート機能そのため、「特殊環境変数」に変換されます。環境変数は、単純なキーと値の文字列のペアのみを使用できます。
bash
シェルがこのタイプの環境変数を使用して環境を継承すると、その変数が関数であることがわかり、bash
適切な名前でその関数をインスタンス化します。
~によるとPOSIX規格:
POSIX.1-2017 シェルのユーティリティおよびユーティリティボリュームは、以下を含む環境変数名を使用します。大文字、数字、および
<underscore>
(_
)移植可能な文字セットの文字で、数字で始まらない。実装では他の文字を受け入れることができます(MAY)。アプリケーションはそのような名前の存在を許可する必要があります。大文字と小文字は一意のアイデンティティを維持し、一緒に折り畳んではいけません。小文字の環境変数名を含む名前空間は、アプリケーション用に予約されています。アプリケーションは、標準ユーティリティの動作を変更することなく、この名前空間の名前を使用して環境変数を定義できます。
この記事によると、%
環境変数を含む名前は許可されていますが/bin/sh
、一部のシステム(dash
Ubuntuやksh
OpenBSDなど)で偽装されているような他のシェルは、環境を整理し、明示的に許可された文字を除く名前に含まれるすべての環境変数を削除します。以外の文字。
/bin/sh
system()
シェルは、アプリケーションが別のプロセスを開始するために呼び出すときに使用されます。
これはすべて意味するあなたが(Ubuntuに)いて、/bin/sh
端末の最後のインタラクティブシェルの環境が呼び出しを介して、または別の方法で(親から子への継承を介して)渡された場合、関数は消えます1。dash
bash
system()
/bin/sh
解決策~/.bashrc
関数は、別名が定義されている場所で定義されます。または、端末にbash
ログインシェルを作成するようにしてください。
1残念ながら、私はGDMやUbuntuを実行していないので、現在のstrace
ログインプロセスに関連するプロセスを実行して、実際に何が起こっているのかを確認することはできません。
別のシェルが呼び出されたときに1つのbash
シェルと別のシェルの間で消える関数を示す例:bash
dash
$ foo () { echo hello; }
$ export -f foo
$ dash -c 'bash -c foo'
bash: foo: command not found
yash
機能を削除しない代替例を使用すると、次のようになります。
$ yash -c 'bash -c foo'
hello
同様にksh
、OpenBSDでクリーンアップ中に次のことをksh93
しないzsh
でください。
$ ksh -c 'bash -c foo'
bash: foo: command not found
$ ksh93 -c 'bash -c foo'
hello
$ zsh -c 'bash -c foo'
hello
上記の出力のすべての場合において、hello
介入シェルは、特に指定された環境変数が関数を形成するという事実を知らない。
$ yash -c 'foo'
yash: no such command `foo'
$ ksh93 -c 'foo'
ksh93: foo: not found
$ zsh -c 'foo'
zsh:1: command not found: foo