web-dev-qa-db-ja.com

シェルスクリプトから.bashrcを正常にソースできません

通常、このコマンドを使用して~/.bashrcファイルをソースできます

source ~/.bashrc

しかし、これをシェルスクリプトで記述して実行しても、何も起こりません。どうして?
これを行う方法はありますか?

私のスクリプト:

#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc

sourceの代わりに.(ドット)も試しました。同じ結果。

49
shantanu

シェルスクリプトは、独自のシェルインスタンスで実行されます。すべての変数設定、関数定義などは、このインスタンス(およびおそらくその子)にのみ影響しますが、呼び出し元のシェルには影響しないため、スクリプトの終了後には削除されます。

対照的に、sourceコマンドは新しいシェルインスタンスを起動しませんが、現在のシェルを使用するため、変更は残ります。

.bashrcを読み取るショートカットが必要な場合は、次のようなシェルスクリプトの代わりにシェル関数またはエイリアスを使用します。

alias brc='source ~/.bashrc'
25
Florian Diesch

試してください:

exec bash

これにより、〜/ .bashrc、〜/ .bash_aliasesなどがリロードされます。

12
Alin Andrei

.bashrcは通常開始します:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

スクリプトにはPS1が設定されていないため(インタラクティブではないため)、早期に終了するため、パスはリセットされません。デモンストレーションするには、スクリプトを変更します。

    #!/bin/bash
    chmod a+x ~/.bashrc
    PS1='$ '
    source ~/.bashrc

これにより、スクリプトが新しい.bashrcで動作できるようになります。注:スクリプトが終了すると、envはスクリプトを開始する前の状態に設定されます。変更は、次に端末を起動したときに反映されます。

12
ravi nankani

私は補完したい ラビの答え

デフォルトの~/.bashrcファイルは、Ubuntu 18.04などのショートサーキットで始まるため、この動作はUbuntu(およびおそらく最も派生したディストリビューション)に固有です。

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

非対話型シェルで実行されているファイルの評価を停止します。これは、スクリプトの場合です。 すべてのスクリプトは非対話型シェルで実行されます であり、その後すべてのファイルsourceはこのプロパティを継承します。

evalハック

evalの代わりにsourceを使用して、Ubuntuを回避するためのいハックを見つけました。

eval "$(cat ~/.bashrc | tail -n +10)"

いくつかの最初の行をスキップして、残りの~/.bashrcを評価するだけなので、残りが評価され、現在の実行が変更されます。

これは魔法の数字であり、Ubuntuのバージョン間で機能しない可能性があることに注意してください。多少なりとも既知のシステム用のスクリプトを作成している場合は、良い解決策かもしれません。

より洗練されたソリューションでは、正規表現を使用して、評価を停止する特定のビットをターゲットにする必要があります。

シバン代替

一部のシナリオでより適切に機能する可能性のある別の代替方法は、 Shebang にフラグを追加することにより、スクリプトを強制的に対話型シェルで実行することです。

#!/bin/bash -i

いくつかのことに注意してください:

  • ベタープラクティス#!/usr/bin/env bashフォームを使用することですが、この方法では 引数でシェルを起動できません です。
  • -iを使用すると、独自の結果セットがありますが、プログラムはユーザーとの対話を促します。これは通常、スクリプトを対象としていません。たとえば、debパッケージをインストールすると、スクリプトが停止します dpkg configureプロンプト
  • 最初にset -iset +iを使用して、必要な場所で機能をオンまたはオフにしようとしましたが、 これは機能しません
10
stefanmaric

他のメソッドはどれも私のために機能しなかった[source /path/to/file vs . ./path/to/file、エイリアスなど...]、まで、このチュートリアルのおかげで このチュートリアル を使用して:

#!/usr/bin/env bash Shebang

単純な#!/usr/bin/envの代わりに、引数をインタープリターに渡すことができます。これがここでのキーだと思います-詳細については、 このドキュメントを参照してください .

いずれにしても、何らかの形式のソースコマンドが機能しない場合は、Shebangを確認してみてください。それが問題の可能性があります。

2
Nikksno