web-dev-qa-db-ja.com

bashで関数を「エクスポート」できますか?

source some_file

some_file:

doit ()
{
  echo doit $1
}
export TEST=true

ソースsome_fileの場合、関数「doit」と変数TESTをコマンドラインで使用できます。しかし、このスクリプトを実行すると:

script.sh:

#/bin/sh
echo $TEST
doit test2

TESTの値を返しますが、不明な関数「doit」に関するエラーを生成します。

関数も「エクスポート」できますか、それとも関数を使用するために、script.shでsome_fileをソースにする必要がありますか?

96
Nils

Bashでは、次のコマンドで関数定義をサブシェルにエクスポートできます

export -f function_name

たとえば、次の簡単な例を試すことができます。

./script1

    #!/bin/bash

    myfun() {
        echo "Hello!"
    }

    export -f myfun
    ./script2

./script2

    #!/bin/bash

    myfun

次に、./script1出力Hello!が表示されます。

142
enzotib

export -fを使用して関数を「エクスポート」すると、関数本体を含む環境変数が作成されます。この例を考えてみましょう:

$ fn(){ echo \'\"\ \ \$; }
$ export -f fn
$ sh -c printenv\ fn
() {  echo \'\"\ \ \$
}

つまり、シェル(Bashだけ?)だけが関数を受け入れることができます。 Bashは() {で始まるenvvarsのみを関数と見なすため、関数を自分で設定することもできます。

$ fn2='() { echo Hi;}' sh -c fn2
Hi
$ fn3='() {' sh -c :
sh: fn3: line 1: syntax error: unexpected end of file
sh: error importing function definition for `fn3'

この変数をSSH経由で「エクスポート」する必要がある場合は、関数を文字列として本当に必要とします。これは、declareビルトインの関数(-p)の印刷オプション(-f)で実行できます。

$ declare -pf fn
fn () 
{ 
    echo \'\"\ \ \$
}

これは、SSH経由で実行する必要があるより複雑なコードがある場合に非常に役立ちます。次の架空のスクリプトについて考えてみます。

#!/bin/bash
remote_main() {
   local dest="$HOME/destination"

   tar xzv -C "$dest"
   chgrp -R www-data "$dest"
   # Ensure that newly written files have the 'www-data' group too
   find "$dest" -type d -exec chmod g+s {} \;
}
tar cz files/ | ssh user@Host "$(declare -pf remote_main); remote_main"
18
Lekensteyn

@ Lekensteyn's answer ...

declare -pfを使用すると、現在のシェルで以前に定義されたすべての関数がSTDOUTに出力されます。

その時点で、STDOUTをどこにでもリダイレクトでき、事実上、以前に定義した関数をどこにでも配置できます。

次の答えはそれらを変数に詰め込みます。次に、その変数と、新しいユーザーとして生成された新しいシェルに実行する関数の呼び出しをエコーし​​ます。これを行うには、Sudo-u(別名。user)スイッチと共に使用し、Bashを実行します(実行する入力としてパイプされたSTDOUTを受け取ります)。

BashシェルからBashシェルに移行することがわかっているので、Bashは以前のシェル定義関数を正しく解釈することがわかっています。同じバージョンの1つのBashシェルから同じバージョンの新しいBashシェルに移動する限り、構文は問題ありません。

異なるシェル間または異なるバージョンのBashを持つシステム間で移動する場合はYMMV。

#!/bin/bash
foo() {
  echo "hello from `whoami`"
}

FUNCTIONS=`declare -pf`; echo "$FUNCTIONS ; foo" | Sudo -u otheruser bash
# $./test.sh
# hello from otheruser
8
Jesse

関数をエクスポートすることはできません。説明した方法ではエクスポートできません。シェルは、対話型シェルの開始時に~/.bashrcファイルのみをロードします( bashのマンページ で「呼び出し」を検索します)。

あなたができることは、あなたがプログラムを開始するときにロードされる「ライブラリ」を作成することです:

source "$HOME/lib/somefile"

そして、そこに非インタラクティブ機能と設定を配置します。

5
Arcege

eval "$(declare -F | sed -e 's/-f /-fx /')"all関数をエクスポートします。

スクリプトでインタラクティブシェルを開始する前に、これをたくさん実行して、関数と変数を使用しながらスクリプトコンテキストでデバッグして作業できるようにします。

例:

eval "$(declare -F | sed -e 's/-f /-fx /')"
export SOME IMPORTANT VARIABLES AND PASSWORDS
bash -i
2
Schlomo

関数はサブプロセスにエクスポートされません。これが、.kshrcまたは.bashrcという名前のファイルがある理由です。サブシェルでも使用できるはずの関数を定義します。

スクリプトを実行している場合、通常、。* shrcスクリプトは提供されません。 . ~/.kshrcのように、それを明示的にコーディングする必要があります。

1
ktf
declare -x -f NAME

より詳しい情報

-fアクションまたは表示を関数名と定義に制限します
-x NAMEをエクスポートします
1
Steven Penny

まあ、私はLinuxは初めてですが、これを試すことができます。いくつかのファイルで、それを 'tmp/general'と呼びましょう。関数を作成します。

func1(){
   echo "func from general"
}

シェルスクリプトに次を追加します。

. /tmp/general

そして実行:

func1

画面に表示されます:func from general

1
noone