bash関数のエイリアススコーピング


9

環境をセットアップする一連のエイリアスを作成するスクリプト(書き込みアクセス権がないスクリプト)を使用しています。環境をセットアップするためのbash関数を作成したいのですが、エイリアスが関数本体まで存続しないようです。

これは最小限の例です:

# aliases.sh
alias fooAlias='echo "this will never work!"'  

# .bashrc
function setupLotsOfThings() {
    source aliases.sh
    fooAlias
}

さて、私が単にaliases.shインタラクティブにソーシングすると、物事は期待通りに機能します:

[mycomputer]~/ $ source aliases.sh
[mycomputer]~/ $ fooAlias
this will never work!

ただし、代わりに.bashrcで定義されている関数を呼び出すと、その定義を取得した後にエイリアスが認識されません。

[mycomputer]~/ $ setupLotsOfThings
-bash: fooAlias: command not found

ここで何が起こっているのですか?alias関数で使用する場合、コマンドのスコープについて何か不足していますか?

編集:私が達成しようとしていることにいくつかの光を当てるために、最小限の例を超えていくつかの詳細を追加します。

私の仕事では、クラスターやグリッドで多くのソフトウェアを開発して実行しています。さまざまなgccバージョン、特定のソフトウェアリリース、構成とデータのPATH、さまざまな環境変数など、まったく異なる環境を必要とするプロジェクトがいくつかあります。管理者は、通常、他の関数やエイリアスを呼び出したり、さまざまなスクリプトを実行したりするシェル関数やエイリアスを定義することによって、さまざまなものを設定するスクリプトを提供します。私にとって、それはブラックボックスです。

一つのコマンドで自分だけの様々な環境をセットアップしたい。現在、私は次のようなことをしています:

[mycomputer]~/ $ source /some/environment/setup/script.sh
[mycomputer]~/ $ aliasToSetupSomeSoftwareVersion    #this was defined in the above
[mycomputer]~/ $ anotherAliasForOtherSoftware
[mycomputer]~/ $ source /maybe/theres/another/script.sh
[mycomputer]~/ $ runSomeOtherSetup      # this was defined in the new script

これらのコマンドは通常、順番に実行する必要があります。私の考えは基本的に上記の行を関数ブロックにコピーすることでしたが、元の例が示すように、それは単に機能しません。代替の回避策は大歓迎です!

回答:


10

代替ソリューションは、これらのコマンドをファンクションブロックではなくテキストファイルに貼り付けることです。何かのようなもの:

## This is needed to make the sourced aliases available
## within the script.
shopt -s expand_aliases

source /some/environment/setup/script.sh
aliasToSetupSomeSoftwareVersion
anotherAliasForOtherSoftware
source /maybe/theres/another/script.sh
runSomeOtherSetup

setup1.sh好きな場所に保存してください。秘訣は、このファイルを実行するのではなく、ソースにすることです。

$ source setup1.sh

これにより、スクリプト内のエイリアスが実行され、現在のシェルで使用できるようになります。

これを以下に追加することで、プロセスをさらに簡略化できます.bashrc

alias setupLotsOfThings="source setup1.sh"

これでsetupLotsOfThings、関数を実行して、必要な動作を関数から取得できます。


説明

ここには2つの問題があります。1つ目は、エイリアスはそれらが宣言されている関数では利用できませんが、その関数が終了したときに1つだけです。2つ目は、エイリアスがスクリプト内で利用できないことです。両方とも同じセクションで説明されていman bashます:

シェルがインタラクティブでない場合は、shoptを使用してexpand_aliasesシェルオプションが設定されていない限り、エイリアスは拡張されません(下記のSHELL BUILTINコマンドの下のshoptの説明を参照してください)。

エイリアスの定義と使用に関するルールはやや混乱します。Bashは常に、その行でコマンドを実行する前に、少なくとも1行の完全な入力を読み取ります。エイリアスは、コマンドが実行されるときではなく、読み取られるときに展開されます。したがって、別のコマンドと同じ行にあるエイリアス定義は、次の入力行が読み込まれるまで有効になりません。その行のエイリアス定義に続くコマンドは、新しいエイリアスの影響を受けません。この動作は、関数が実行されるときの問題でもあります。 関数定義はそれ自体が複合コマンドであるため、関数の実行時ではなく、関数定義の読み取り時にエイリアスが展開されます。結果として、関数で定義されたエイリアスは、
その関数が実行されるまで使用できません。
安全のために、エイリアスの定義は常に別の行に記述し、複合コマンドではエイリアスを使用しないでください。

次に、ファイルの実行とソースの間に違いがあります。基本的に、スクリプトを実行すると、別のシェルで実行されますが、ソースを実行すると、現在のシェルで実行されます。そのため、ソースsetup.shを使用すると、エイリアスを親シェルで使用できるようになりますが、スクリプトでは実行できません。


ええと、私はクラスタで作業しており、ソフトウェア環境のセットアップなどに役立つ、このような「エイリアス」スクリプトをいくつか用意しています。エイリアススクリプトは、さまざまなエイリアスを定義します。私の目標は、正しいエイリアスを取得して特定の環境を呼び出し、それらのエイリアス(の一部)を実行することです。複数のコマンドを順番に実行する必要があるのではなく、1つのコマンドでこれを実行したい
2014年

そしてPSエイリアスを設定するスクリプトは残念ながら非常に冗長で少し遅い(NFS上の多くのファイルに触れるため)ので、たとえばログイン時にこれらすべてのものをソースすることは好みません。
2014年

@chaseですがsetupLotsOfThings、それらはを実行したときにのみ取得され、関数自体では使用できません。それらは、関数を呼び出したシェルから機能します。とにかく、関数がエイリアスのみをソースしている場合、なぜエイリアスを使用しないのですか?次に例を示しますalias setupstuff="source aliases.sh"
terdon 2014年

そうですが、スコープ自体は心配していません。理想的には、「ソーススタッフ」と「実行エイリアス」のステップを1つに結合したいだけです。多分それは3つの機能で行うことができますか?function sourceStuff(){source ...}; function runStuff(){someAlias; ...}; function setupLotsOfThings(){sourceStuff; runStuff; };
2014年

@chaseええ、私はそれを考えましたが、うまくいきませんでした:) あなたがする必要があることのいくつかのより多くであなたの質問を広げることができますか?関数は非常に複雑な処理しかできないため、代わりに小さなスクリプトを作成する必要がある場合があります。
terdon 2014年

7

実際、エイリアスは関数が読み込まれた後に利用可能になります!これらは、インタラクティブシェルで、または.bashrc関数の実行後に使用できます。

制限は、関数が評価されるときではなく、関数定義が読み取られるときに、関数定義のエイリアスが展開されることです。これはbashの制限です。だからこれはうまくいくでしょう:

function setupLotsOfThings() {
    source aliases.sh
}
setupLotsOfThings
fooAlias

しかし、これではありません:

function setupLotsOfThings() {
    source aliases.sh
}
function useTheAliases() {
    fooAlias
}
setupLotsOfThings
useTheAliases

関数内で使用でき、関数の解析後に定義できるエイリアスが必要な場合は、代わりにそれらを関数にします。commandビルトインを使用して、同じ名前の関数から外部コマンドを呼び出すことができることに注意してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.