GNU/Linux >> Linux の 問題 >  >> Linux

ps:コマンド全体が長すぎます

Linux では、ps を使用 procps(-ng) から :

ps -fwwp 2755

4.2 より前の Linux バージョンでは、まだ制限されています (カーネル (/proc/2755/cmdline ) から 4k) まで、プロセスに指示するか、デバッガを使用する以外に、それ以上の値を取得することはできません。

$ sh -c 'sleep 1000' $(seq 4000) &
[1] 31149
$ gdb -p $! /bin/sh
[...]
Attaching to program: /bin/dash, process 31149
[...]
(gdb) bt
#0  0x00007f40d11f40aa in wait4 () at ../sysdeps/unix/syscall-template.S:81
[...]
#7  0x00007f40d115c995 in __libc_start_main (main=0x4022c0, argc=4003, ubp_av=0x7fff5b9f5a88, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff5b9f5a78)
at libc-start.c:260
#8  0x00000000004024a5 in ?? ()
#9  0x00007fff5b9f5a78 in ?? ()
#10 0x0000000000000000 in ?? ()
(gdb) frame 7
#7  0x00007f40d115c995 in __libc_start_main (main=0x4022c0, argc=4003, ubp_av=0x7fff5b9f5a88, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff5b9f5a78)
at libc-start.c:260
(gdb) x/4003s *ubp_av
0x7fff5b9ff83e: "sh"
0x7fff5b9ff841: "-c"
0x7fff5b9ff844: "sleep 1000"
0x7fff5b9ff84f: "1"
0x7fff5b9ff851: "2"
[...]
0x7fff5ba04212: "3999"
0x7fff5ba04217: "4000"

4 番目の引数を最大 5000 文字で出力するには:

(gdb) set print elements 5000
(gdb) p ubp_av[3]

邪魔にならないものが必要な場合は、 /proc/2755/mem から情報を取得してみてください (kernel.yama.ptrace_scope が 0 に設定されていない場合、そのためにはスーパーユーザー権限が必要になります)。以下は私にとってはうまくいきます (すべての引数と環境変数を出力します) が、私が考える保証はあまりありません (エラーと予期しない入力処理は、読者への演習として残されています):

$ perl -e '$p=shift;open MAPS, "/proc/$p/maps";
          ($m)=grep /\[stack\]/, <MAPS>;
          ($a,$b)=map hex, $m =~ /[\da-f]+/g;
          open MEM, "/proc/$p/mem" or die "open mem: $!";
          seek MEM,$a,0; read MEM, $c,$b-$a;
          print((split /\0{2,}/,$c)[-1])' "$!" | tr \\0 \\n | head
sh
-c
sleep 1000
1
2
3
4
5
6
7

("$!" を置き換えます プロセス ID と一緒に)。上記は、Linux が argv[] が指す文字列を置くという事実を利用しています。 、 envp[] プロセスのスタックの一番下にある実行されたファイル名。

上記は、2 つ以上の連続した NUL バイトの 2 つのセットの間にある一番下の文字列のスタックを調べます。引数またはenv文字列のいずれかが空の場合、それらのargvまたはenvpの真ん中に2つのNULバイトのシーケンスがあるため、機能しません。また、argv 文字列がどこで停止し、envp 文字列がどこで開始するかはわかりません。

そのための回避策は、argv[] の実際のコンテンツを逆に見て、そのヒューリスティックを改良することです。 (ポインター)。以下は、少なくとも ELF 実行可能ファイルの i386 および amd64 アーキテクチャで動作します:

perl -le '$p=shift;open MAPS, "/proc/$p/maps";
      ($m)=grep /\[stack\]/, <MAPS>;
      ($a,$b)=map hex, $m =~ /[\da-f]+/g;
      open MEM, "/proc/$p/mem" or die "open mem: $!";
      seek MEM,$a,0; read MEM, $c,$b-$a;
      $c =~ /.*\0\0\K[^\0].*\0[^\0]*$/s;
      @a=unpack"L!*",substr$c,0,$-[0];
      for ($i = $#a; $i >=0 && $a[$i] != $a+$-[0];$i--) {}
      for ($i--; $i >= 0 && ($a[$i]>$a || $a[$i]==0); $i--) {}
      $argc=$a[$i++];
      print for unpack"(Z*)$argc",substr$c,$a[$i]-$a;' "$!"

基本的には上記と同じですが、argv[] の最初の文字列が見つかったら (または argv[] の少なくとも 1 つ または envp[] 空がある場合は文字列)、そのアドレスを知っているので、スタックの一番上の残りを逆方向に検索して、同じ値を持つポインターを探します。次に、それらへのポインターにならない数値、つまり argc が見つかるまで、逆方向に検索し続けます。 .次の整数は argv[0] です .そしてargv[0]を知る と argc 、引数のリストを表示できます。

プロセスが argv[] に書き込んだ場合、それは機能しません おそらくいくつかの NUL 区切り文字をオーバーライドするか、または argc の場合 0 (argc 通常、argv[0] を含めるには少なくとも 1 です。 ) しかし、少なくとも ELF 実行可能ファイルの一般的なケースでは機能するはずです。

4.2 以降では、/proc/<pid>/cmdline 切り捨てられなくなりましたが、ps それ自体の最大表示幅は 128K です。


1 つまたは 2 つの -w を追加します フラグ。出力の幅が広がります。例えばps auxww .


Linux カーネル 4.2 以降では、/proc/<pid>/cmdline 切り捨てられなくなり、次のようにうまく動作します:

xargs -0 printf '%s\n' < /proc/2755/cmdline

Linux
  1. コマンドが見つからないのになぜ長い遅延があるのですか?

  2. 「引数リストが長すぎます」というエラーでディレクトリからファイルを削除できない

  3. SFTP エラー 受信メッセージが長すぎます

  1. rm、cp、mv コマンドの引数リストが長すぎるというエラー

  2. 断続的な OSError:[Errno 7] 引数リストが短いコマンドで長すぎます (~125 文字)

  3. Linux コマンドラインの文字制限

  1. Ubuntu –引数リストが長すぎますか?

  2. 長いスリープコールの後、Sudoパスワードを再入力せずにSudoコマンドを実行しますか?

  3. Linuxmvコマンド