できること
linuxサーバーでの作業履歴を記録する。
履歴をとっていることがバレにくい。
ssh接続時はアクセス元の記録もできる。
前提条件
OS: Linux
シェル: bash
やり方
結論から。
if [ "$SHLVL" = "1" ] && [ ! -z "$PS1" ]
then
[ -d ~/scripts/ ] || mkdir ~/scripts
find ~/scripts/ -type f -mtime +60 -delete
export Guest=`who am i`
date=`date +script_%F_%T`
LANG=C script -qft 2>~/scripts/$date.time ~/scripts/$date.log
exit
elif [ `ps aux | grep $PPID | grep -v grep | awk '{ print $11 }'` = "script" ]
then
echo $Guest
fi
scriptで履歴を取得
単体で .bashrc
に書くと 無限ループ になります。
date=`date +script_%F_%T`
LANG=C script -qft 2>~/scripts/$date.time ~/scripts/$date.log
- dateコマンドで、日付をフォーマットする。「script_2022-12-31_12:59:59」
- scriptコマンドで履歴を取得
-
LANG=C
: 日本語だと後に利用するscriptreplay
がうまくいかないため。scriptreplay
を使わないならなくてもいい。 -
-q
: scriptコマンドを開始、終了した旨のメッセージを非表示にする。これがないと記録してるのがバレバレ。 -
-f
: 記録をリアルタイムで参照できるようにする。なくても構わない。 -
-t
: 文字を入力した時間を標準エラー出力に出力する。scriptreplay
を使うなら必須。 -
2>~/scripts/$date.time
:-t
で出力された時間をファイルにリダイレクトする。これがないと色々と大変なことになるので、-t
をつけるなら絶対つけること。 -
~/scripts/$date.log
: ログ出力先のファイル。
-
script
は子シェルを生成し、その中でコマンドを実行させる。そのため、これを単体で書くと生成されたシェルでさらにscript
がシェルを生成し、無限ループになる。
無限ループにならないようにする。
if [ "$SHLVL" = "1" ] && [ ! -z "$PS1" ]
$SHLVL
はシェルの深度。script
コマンド下ではこれが2になるため判別できる。
$PS1
はプロンプト。空文字でないことを実行条件としている。
アクセス元を記録
アクセス元のIPは、アクセス直後のシェルでwho am i
を実行すると取得できる。
ただ、script
下で実行しても取得できない。
そこで、script
実行前に取得して環境変数に入れておき、script
下で出力することで記録させている。
if [ "$SHLVL" = "1" ] && [ ! -z "$PS1" ]
then
export Guest=`who am i`
elif [ `ps aux | grep $PPID | grep -v grep | awk '{ print $11 }'` = "script" ]
then
echo $Guest
fi
ps aux | grep $PPID | grep -v grep | awk '{ print $11 }'
で親プロセスの名称を取得している。
-
ps aux
: プロセス一覧を取得 -
grep $PPID
: 親プロセスのPID($PPID
)が含まれるもので絞り込み -
grep -v grep
: 上記にはこのコマンド自身も含まれてしまうので、grep
が含まれていないものを抽出。これで親プロセスだけになった。 -
awk '{ print $11 }'
: スペース区切りで11個目であるプロセス名を取得。親プロセスがscript
コマンドであればscript
が入る。
諸々追加
保存先のフォルダがなければ作る (任意)
[ -d ~/scripts/ ] || mkdir ~/scripts
60日以上前のログを削除 (任意)
find ~/scripts/ -type f -mtime +60 -delete
exit
コマンドを一回で済ませる
LANG=C script -qft 2>~/scripts/$date.time ~/scripts/$date.log
exit
通常、script
コマンドを実行中にシェルを抜けるにはexit
を二回入力する必要がある。
しかし、script
終了時に自動的にexit
を実行すれば、一回で済ませられる。
これにより、ログの取得がほぼバレなくなる。
結果の再掲
if [ "$SHLVL" = "1" ] && [ ! -z "$PS1" ]
then
[ -d ~/scripts/ ] || mkdir ~/scripts
find ~/scripts/ -type f -mtime +60 -delete
export Guest=`who am i`
date=`date +script_%F_%T`
LANG=C script -qft 2>~/scripts/$date.time ~/scripts/$date.log
exit
elif [ `ps aux | grep $PPID | grep -v grep | awk '{ print $11 }'` = "script" ]
then
echo $Guest
fi