端末履歴をhist.txtというファイルに保存するbashスクリプトを作成しようとしています。 history > hist.txt
の使用はbashスクリプトでは機能しないようですが、コマンドラインで実行すると正常に機能します。
どんなガイダンスも大歓迎です。
ありがとうジュディ
source
または.
を使用してスクリプトを実行します。
source ./script_name.sh
または
. ./script_name.sh
後者は、異なるシェル間でわずかに互換性があります。
この質問は重要なポイントを強調しています。つまり、シェルスクリプトは独自のコンテキストで実行されるということです。これが何を意味するかを確認するには、次のシェルスクリプトを検討してください。
#!/bin/bash
cd /
ls
これを実行すると、次のような出力が得られます。
bin boot dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
ただし、スクリプトを実行した後、実行前のディレクトリにいることに気付くでしょう。スクリプト内のcd /
は、実際にはセッションに影響を与えていません。スクリプトが実行されるために作成され、スクリプトが戻ると破棄されました。
source
コマンドは「現在のシェルコンテキストのファイル名引数からコマンドを読み取って実行する」ため、その中のcd
などのコマンドは現在のセッションに影響します。上記のスクリプトをsource
に渡して実行する場合、実行後にルートディレクトリ内で終了することがわかります。
この場合、問題はhistory
コマンドが現在のシェルコンテキストの履歴を提供することです。 source
を使用せずにスクリプトを実行するシェルコンテキストには履歴がないため、出力ファイルには何も書き込まれません。 source
を使用すると、正しいコンテキストで実行され、期待どおりに機能します。
NB:source
はシェルではなくプログラムです本質的に-Bashでは、source
は.
と同義ですが、一部のシェルでは.
は機能します-.
より読みやすいので、この回答でsource
を使用しましたが、最大限の互換性を確保するには.
を使用する必要があります。
まず、履歴が既にファイルにあることに注意してください。 bashを実行している場合、その名前は通常~/.bash_history
です。具体的には、変数HISTFILE
を設定したものです。別のファイルにコピーする場合は、cat "$HISTFILE" > hist.txt
を実行するだけです
ここで、history
コマンドがbashシェルスクリプトで機能しない理由については、現在のシェルセッションの非対話型の子シェルでスクリプトが実行されるためです。子シェルは親のすべての環境を継承するわけではなく(設定された変数のすべてを継承するわけではありません)、エクスポートされた変数のみを継承します。説明のために、以下のスクリプトは変数$var
の値をエコーします。
#!/bin/bash
echo "$var"
次に、$var
を何かに設定して、スクリプトを実行します。
$ var="foo"
$ foo.sh
VAR:
次に、最初に変数をエクスポートします。
$ var="foo"
$ export var
$ foo.sh
VAR: foo
ご覧のとおり、変数がエクスポートされると、子シェルで使用できます。
前述したように、履歴は変数$HISTFILENAME
が指すファイルに保存されます。これはデフォルトではエクスポートされないため、スクリプトの実行時には設定されません。
$ cat foo.sh
#!/bin/bash
echo "HISTFILE: $HISTFILE"
$ ./foo.sh
HISTFILE:
$ echo $HISTFILE
/home/terdon/.bash_history
上記の例でわかるように、変数HISTFILE
は通常のシェルセッションで設定されていますが、スクリプトの実行時には空です。
したがって、履歴を取得するには、いくつかのオプションがあります。
デフォルトのHISTFILE
値は$HOME/.bash_history
です。変更していない場合は、スクリプトで次のコマンドを実行するだけです。
cat "$HOME/.bash_history" > history
$HISTFILE
変数をスクリプトに渡し、cat
を渡すことができます。
#!/bin/bash
cat "$1" > history
上記をfoo.sh
として保存し、次のように実行します。
./foo.sh "$HISTORY"
変数がエクスポートされていることを確認してください。この行を~/.bash_profile
(存在する場合)または~/.profile
(~/.bash_profile
が存在しない場合)ファイルに追加します。
export HISTFILE
その後、ログアウトして再度ログインすると、期待どおりにスクリプトからhistory > hist.txt
を実行できるはずです。これは、export VAR
が「子シェルで$ VARを使用可能にする」ことを意味するためです。実際的には、これは、HISTFILE
の値が、スクリプトの実行に使用する非対話型シェルに継承されることを意味します。
これで、HISTFILE
が設定されますが、スクリプトを実行するシェルによって読み取られていません。したがって、それを機能させるには、最初にhistory -r
で読む必要があります。スクリプト全体は次のようになります。
$!/bin/bash
history -r
history > hist.txt
または、スクリプトを実行する前に手動でエクスポートするだけです。
$ export HISTFILE
ただし、スクリプトではhistory -r
が必要です。
@ p0llard's answer で提案されているように、source
できます。