スクリプトによるbashインスタンスの制御(強力な方法)

スクリプトによるbashインスタンスの制御(強力な方法)

いくつかの(最後にインタラクティブな)スクリプト(Pythonなど)を使用して、いくつかのbashプログラム(ローカルまたはssh)を強力な方法で制御したいと思います。コマンドを送信し、実行が終わったらコマンドのstdout/stderrとコマンドの終了コードを取得したいと思います。 bashコマンドは、外部ユーザーがリアルタイムで選択するため、どのコマンドでも可能です。

私が望むものを理解するために関数を提供したいです(プログラミング言語は重要ではありません)。

def send_command(command):
    # how to implement ????
    return (stdin_output, stderr_output, exit_code)

これにより、次のように実行できます。

(o,e,ex) = send_command("pwd")
print("The output of your last command is ", o)
(o,e,ex) = send_command("cd /tmp")
(o,e,ex) = send_command("pwd")
print("The output of your last command is ", o)

これで以下が生成されます。

The output of your last command is /home/me/
The output of your last command is /tmp/

commandまた、誰も私のPythonスクリプトを「台無しにする」ことができず、実際には完了していませんが、コマンドが完了したと信じさせたいと思います。たとえば、私は彼が従うすべてのコマンドを記録したくないので、次のコードは最初の行から永久にブロックする必要があります(最初のコマンドは無限ループです)、2番目の行を呼び出さないでください。

send_command("echo $PS1; <malicious command that loops forever and sends all the next inputs to a webserver>")
send_command("echo mysecretpassword") # This line should never be executed

私が試したこと:

1つのオプションは、毎回新しいbashインスタンスを実行し、このコンソールでスクリプトを実行することです。しかし、ここには2つの欠点があります。まず、毎回最初からbash / sshをロードするので、それほど効率的ではありません。第二に、bashの状態(環境、作業ディレクトリ)は実行されるたびに新しいものです。例:「cd /tmp」を実行すると、次のコマンドで自宅になります。

私が見たもう一つのオプションはexpect/ですpexpect。この解決策の問題は、私が知っている限り出力を解析することだけです。この解析は bash 出力の意味を失います。たとえば、期待している場合は、$コマンドが完了したことを確認する方法がなく、コマンド自体がこのテキストを作成することもできます。同様に、プログラムが完全に信頼できない場合、状況はさらに悪化する可能性があります。プログラムはbashを偽装し、すべてのbashコマンドを読み取ることができます。複雑なPS1設定を試すこともできますが、この環境変数はコマンドに渡されるため、この変数(「env」など)を出力するすべてのプログラムはコマンドを中断するため、実際には信頼できるソリューションではありません。最後に、最後に入力したコマンドのコードを出力するbashコマンドを実行し、この結果を解析するよりもコマンド終了コードを取得する「良い」方法はありません。

3番目のオプションを見逃しましたか?

ありがとうございます!

- 編集 - 環境変数について調べましたが、PROMPT_COMMAND私が知っている限り、環境変数には送信されません。しかし、まだシェルから直接読むことができる簡単な方法があるので、echoそれほど強力ではありません。

$ PS1=""
PROMPT_COMMAND='echo -n "Prompt MYSECRETNUMBERSETBYEXPECT (last exit $?) "'                             
Prompt MYSECRETNUMBERSETBYEXPECT (last exit 0) ls /tmp/o
file.txt
Prompt MYSECRETNUMBERSETBYEXPECT (last exit 0) rm /tmp/a/donotexist
rm: impossible de supprimer '/tmp/a/donotexist': No such file or directory
Prompt MYSECRETNUMBERSETBYEXPECT (last exit 1) env | grep SECRET
Prompt MYSECRETNUMBERSETBYEXPECT (last exit 1)

- 編集2 - より強力に見えるもう1つの解決策は、ランダムな秘密のヒントを使用してpexpectから次のものを含めることですcommand

PS1=""; <command>; PS1="My secret PS1 61547851396512fdsqjklqdf (last code $?) >>$ "

(このコードは、コマンドがプロンプト値にアクセスできないようにコマンドの前後にPS1シークレットプロンプトを削除/再生成します<command>)とセミコロンを忘れないでください)。{ <command>; } > /tmp/out.stdout 2> /tmp/out.stderrこれが進む最善の方法ですか?

答え1

試してみることができますsysdig、これは基本的にシステム用のスパイウェアです。
~からsysdiog Wiki以下を使用してstdoutプロセス名で観察できますcat

sysdig -s4096 -A -c stdout proc.name=cat

foo次の名前のユーザーが実行したすべてのコマンドを監視することもできます。

sysdig -c spy_users user.name=foo

このStackExchangeの質問を参照することもできます。

https://stackoverflow.com/questions/54771786/record-bash-interaction-saving-stdin-stdout-seperately

あなたのために考えることがたくさんあります。

関連情報