端末履歴をbashファイルからファイルに保存する方法は?


7

端末の履歴をhist.txtというファイルに保存するbashスクリプトを作成しようとしています。使用history > hist.txtはbashスクリプトでは機能しないようですが、コマンドラインで実行すると正常に機能します。

どんなガイダンスも大歓迎です。

ありがとうジュディ


3
あなたの質問は少し混乱しています。「bashファイルでは機能しないようですが、コマンドラインで実行すると正常に機能する」とはどういう意味ですか?実行中のbashスクリプト内からコマンド履歴を保存しようとしているのですか?あなたがスクリプトによって実行されたコマンドを保存したいのですか?この場合、スクリプト自体は履歴です。
Stephen

6
または、特定のユーザーのbash履歴を出力しますか?ユーザーの~/.bash_historyファイルを読み取るだけです。
Arronical、2016

1
@Arronicalは、ユーザーがシェルとしてBashを使用している場合にのみ機能することに注意してください。常にそうであるとは限りません。

1
@ p0llardもちろん、私はBashスクリプトの場合と同様に、ユーザーのシェルとしてはBashであると想定していきましたが、そうではない可能性があります。ところであなたの答えの良い詳細と背景。
アロニカル2016

回答:


11

簡潔な答え

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コマンドは、「読み取りと現在のシェルのコンテキストでfilename引数からコマンドを実行する」のような任意のコマンドので、うcd、その中には現在のセッションに影響します。上記のスクリプトを渡して実行すると、実行source後にルートディレクトリ内に移動することになります。

この場合の問題は、historyコマンドが現在のシェルコンテキストの履歴を提供することです。スクリプトを使用せずに実行するシェルコンテキストにsourceは履歴がないため、出力ファイルには何も書き込まれません。使用sourceすると、正しいコンテキストで実行され、期待どおりに動作します。

NBは:sourceシェルは、内蔵されて、いないプログラム自体 -バッシュでは、sourceと同義である.が、一部のシェルでのみが.動作します-私が使用したsource、それはより読みやすいですので、この答えで.はなく、最大の互換性のために、.するべき利用される。


非常に興味深い読み物。私は常に「欠落した」履歴コマンドについて疑問に思っていましたが、今はその理由がわかります。ありがとう!
Tico

10

まず第一に、あなたの履歴はすでにファイルにあることに注意してください。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は通常のシェルセッションで設定されていますが、スクリプトの実行時には空です。

したがって、履歴を取得するには、いくつかのオプションがあります。

  1. デフォルトHISTFILE値は$HOME/.bash_historyです。それを変更していない場合は、スクリプトで次のコマンドを実行するだけです。

    cat "$HOME/.bash_history" > history
  2. $HISTFILE変数をスクリプトに渡すことができますcat

    #!/bin/bash
    cat "$1" > history

    上記を保存して、次のようにfoo.sh実行します。

    ./foo.sh "$HISTORY"
  3. 変数がエクスポートされていることを確認してください。この行を~/.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スクリプトで行う必要があります。

  4. @ p0llardの回答でsource提案されているようにできます

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