এই ইউনিক্স সকেট পেয়ারের অন্য প্রান্তটি কে পেয়েছে?


54

কোন ইউনিক্স সকেটের অন্য প্রান্তটি রয়েছে তা আমি নির্ধারণ করতে চাই।

বিশেষত, আমি যেটি তৈরি করা হয়েছিল তার একটি সম্পর্কে জিজ্ঞাসা করছি socketpair(), যদিও কোনও ইউনিক্স সকেটের ক্ষেত্রে সমস্যাটি একই রকম।

আমার একটি প্রোগ্রাম রয়েছে parentযা একটি socketpair(AF_UNIX, SOCK_STREAM, 0, fds)এবং fork()এস তৈরি করে । পিতামাতার প্রক্রিয়াটি বন্ধ হয়ে যায় fds[1]এবং fds[0]যোগাযোগ চালিয়ে যায় । শিশু বিপরীত কাজ করে close(fds[0]); s=fds[1],। তারপরে বাচ্চাটি exec()অন্য একটি প্রোগ্রাম child1,। দু'জন এই সকেট পেয়ারের মাধ্যমে পিছনে পিছনে যোগাযোগ করতে পারে।

এখন, আসুন আমি বলি আমি কে জানি parentতবে কে তা কে খুঁজে বের করতে চাই child1। আমি এটা কিভাবে করবো?

আমার নিষ্পত্তি করার জন্য বেশ কয়েকটি সরঞ্জাম রয়েছে তবে সকেটের অপর প্রান্তে কোন প্রক্রিয়া চলছে তা কেউ আমাকে বলতে পারে না। আমি চেষ্টা করেছি:

  • lsof -c progname
  • lsof -c parent -c child1
  • ls -l /proc/$(pidof server)/fd
  • cat /proc/net/unix

মূলত, আমি দুটি সকেট এবং সেগুলি সম্পর্কে সমস্ত কিছু দেখতে পাচ্ছি তবে তারা সংযুক্ত কিনা তা বলতে পারছি না। আমি নির্ধারণ করার চেষ্টা করছি যে পিতামাতার মধ্যে কোন এফডি কোন শিশু প্রক্রিয়াটির সাথে যোগাযোগ করছে।

উত্তর:


27

কার্নেল ৩.৩, যেহেতু এটি ব্যবহার করা ssবা তারওlsof-4.89 বেশি সম্ভব - স্টাফেন চেজেলাসের উত্তর দেখুন

পুরানো সংস্করণগুলিতে, লেখকের মতে lsofএটি খুঁজে পাওয়া অসম্ভব: লিনাক্স কার্নেল এই তথ্যটি প্রকাশ করে না। উত্স: 2003. থ্রেড comp.unix.admin এ

প্রদর্শিত নম্বরটি /proc/$pid/fd/$fdহ'ল ভার্চুয়াল সকেট ফাইল সিস্টেমে সকেটের ইনোড নম্বর। আপনি যখন পাইপ বা সকেট জুটি তৈরি করেন, প্রতিটি প্রান্ত পরপর একটি ইনোড নম্বর পায়। সংখ্যাগুলি ধারাবাহিকভাবে চিহ্নিত করা হয়, সুতরাং উচ্চ সম্ভাবনা রয়েছে যে সংখ্যাগুলি 1 দ্বারা পৃথক হয়, তবে এটি গ্যারান্টিযুক্ত নয় (হয় কারণ প্রথম সকেটটি এন এবং এন +1 ইতিমধ্যে মোড়ানোর কারণে ব্যবহৃত হয়েছিল, বা কারণ অন্য কোনও থ্রেড ছিল দুটি ইনোড বরাদ্দের মধ্যে নির্ধারিত এবং সেই থ্রেডটি কিছু ইনোড তৈরি করেছে)।

আমি কার্নেল ২.6.৩৯- এর সংজ্ঞাটিsocketpair পরীক্ষা করে দেখেছি এবং সকেটের দুটি প্রান্ত টাইপ-নির্দিষ্ট socketpairপদ্ধতি ব্যতীত পারস্পরিক সম্পর্কযুক্ত নয় । ইউনিক্স সকেটের জন্য, এটি unix_socketpairভিতরেnet/unix/af_unix.c


2
ধন্যবাদ @ জিলস আমি কিছুক্ষণ আগে এই সম্পর্কে কিছু পড়ার কথা মনে করি, কিন্তু এটি আবার খুঁজে পেতে পারি নি। আমি কেবল / প্রো / নেট / ইউনিক্সের জন্য প্যাচ লিখতে যেতে পারি।
জোনাথন রাইনহার্ট

এবং হ্যাঁ, আমি ক্রমবর্ধমান ইনোড সংখ্যা নিয়ে এই পর্যবেক্ষণ করেছি এবং বর্তমানে আমি এটাই নিয়ে কাজ করছি। তবে, যেমন আপনি উল্লেখ করেছেন, এটির নিশ্চয়তা নেই। আমি যে প্রক্রিয়াটি দেখছি তাতে কমপক্ষে 40 টি উন্মুক্ত ইউনিক্স সকেট রয়েছে এবং আমি এমন একটি উদাহরণ দেখেছি যেখানে এন +1 সত্য রাখে না। হতাশাজনক।
জোনাথন রাইনহার্ট

1
@ জোনাথনরাইনহার্ট আমি সংজ্ঞাটিsocketpair পরীক্ষা করেছিলাম এবং সকেটের দুটি প্রান্ত টাইপ-নির্দিষ্ট socketpairপদ্ধতি ব্যতীত পারস্পরিক সম্পর্কযুক্ত নয় । ইউনিক্স সকেটের জন্য, এটি unix_socketpair`নেট / ইউনিক্স / আফ_উনিক্স.সি . পাইপগুলির জন্যও এই তথ্যটি পাওয়া ভাল লাগবে।
গিলস 'তাই খারাপ হওয়া বন্ধ করুন'

36

দ্রষ্টব্য : আমি এখন এখানে একটি lsofবর্ণনাকারী রক্ষণাবেক্ষণ করেছি যা এখানে বর্ণিত উভয় পদ্ধতির সমন্বয় করে এবং লুপব্যাক টিসিপি সংযোগের পিয়ার্সের জন্য https://github.com/stephane-chazelas/misc-scriptts/blob/master/lsofc এ যোগ করি

লিনাক্স -৩.৩ এবং তারপরে।

লিনাক্স-এ, কার্নেল সংস্করণ ৩.৩ (যে UNIX_DIAGবৈশিষ্ট্যটি কার্নেলের মধ্যে নির্মিত হয়েছে), একটি নতুন ইউনিক্স ডোমেন সকেটের (সকেটপেইস অন্তর্ভুক্ত) পিয়ারটি একটি নতুন নেট লিঙ্ক ভিত্তিক এপিআই ব্যবহার করে প্রাপ্ত করা যেতে পারে ।

lsof সংস্করণ ৪.৯৯ যেটি এপিআই ব্যবহার করতে পারে:

lsof +E -aUc Xorg

সমস্ত ইউনিক্স ডোমেন সকেটের তালিকা তৈরি করবে যেগুলির একটি প্রক্রিয়া রয়েছে যার নামটি Xorgউভয় প্রান্তে শুরু হয় এর অনুরূপ বিন্যাসে:

Xorg       2777       root   56u  unix 0xffff8802419a7c00      0t0   34036 @/tmp/.X11-unix/X0 type=STREAM ->INO=33273 4120,xterm,3u

যদি আপনার সংস্করণটি lsofখুব পুরানো হয় তবে আরও কয়েকটি বিকল্প রয়েছে।

ss(থেকে উপযোগ iproute2) যে একই API ব্যবহার করতে পুনরুদ্ধার করতে এবং পিয়ার তথ্য সহ সিস্টেমে UNIX ডোমেইন সকেট তালিকায় তথ্য প্রদর্শন করে তোলে।

সকেটগুলি তাদের ইনোড নম্বর দ্বারা চিহ্নিত করা হয় । মনে রাখবেন এটি সকেট ফাইলের ফাইল সিস্টেম ইনোডের সাথে সম্পর্কিত নয়।

উদাহরণস্বরূপ:

$ ss -x
[...]
u_str  ESTAB    0    0   @/tmp/.X11-unix/X0 3435997     * 3435996

এটিতে বলা হয়েছে যে সকেট 3435997 (এটি আবস্ট্রাক্ট সকেটের সাথে আবদ্ধ ছিল /tmp/.X11-unix/X0) সকেটের সাথে 3435996 সংযুক্ত রয়েছে option -pবিকল্পটি আপনাকে বলতে পারে কোন সক্রিয়তার (এস) সেই সকেটটি খোলা আছে। এটি কিছুটা readlinkচালিয়ে যাওয়ার দ্বারা এটি করে /proc/$pid/fd/*, সুতরাং এটি কেবলমাত্র আপনার নিজের প্রক্রিয়াগুলিতে (আপনি না থাকলে root) এগুলি করতে পারে । উদাহরণস্বরূপ এখানে:

$ sudo ss -xp
[...]
u_str  ESTAB  0  0  @/tmp/.X11-unix/X0 3435997 * 3435996 users:(("Xorg",pid=3080,fd=83))
[...]
$ sudo ls -l /proc/3080/fd/23
lrwx------ 1 root root 64 Mar 12 16:34 /proc/3080/fd/83 -> socket:[3435997]

কী প্রক্রিয়া (এস) এর 3435996 রয়েছে তা খুঁজে পেতে, আপনি তার আউটপুটটিতে এর নিজস্ব এন্ট্রি সন্ধান করতে পারেন ss -xp:

$ ss -xp | awk '$6 == 3435996'
u_str  ESTAB  0  0  * 3435996  * 3435997 users:(("xterm",pid=29215,fd=3))

আপনি lsofসহজেই প্রাসঙ্গিক তথ্যটি প্রদর্শন করতে এই স্ক্রিপ্টটিকে চারপাশে মোড়ক হিসাবে ব্যবহার করতে পারেন:

#! /usr/bin/perl
# lsof wrapper to add peer information for unix domain socket.
# Needs Linux 3.3 or above and CONFIG_UNIX_DIAG enabled.

# retrieve peer and direction information from ss
my (%peer, %dir);
open SS, '-|', 'ss', '-nexa';
while (<SS>) {
  if (/\s(\d+)\s+\*\s+(\d+) ([<-]-[->])$/) {
    $peer{$1} = $2;
    $dir{$1} = $3;
  }
}
close SS;

# Now get info about processes tied to sockets using lsof
my (%fields, %proc);
open LSOF, '-|', 'lsof', '-nPUFpcfin';
while (<LSOF>) {
  if (/(.)(.*)/) {
    $fields{$1} = $2;
    if ($1 eq 'n') {
      $proc{$fields{i}}->{"$fields{c},$fields{p}" .
      ($fields{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
    }
  }
}
close LSOF;

# and finally process the lsof output
open LSOF, '-|', 'lsof', @ARGV;
while (<LSOF>) {
  chomp;
  if (/\sunix\s+\S+\s+\S+\s+(\d+)\s/) {
    my $peer = $peer{$1};
    if (defined($peer)) {
      $_ .= $peer ?
            " ${dir{$1}} $peer\[" . (join("|", keys%{$proc{$peer}})||"?") . "]" :
            "[LISTENING]";
    }
  }
  print "$_\n";
}
close LSOF or exit(1);

উদাহরণ স্বরূপ:

$ sudo that-lsof-wrapper -ad3 -p 29215
কম্যান্ড পিআইডি ব্যবহারকারী এফডি টাইপ ডিভাইস সাইজ / কোনও নাম বাদ নেই
xterm 29215 স্টেফেন 3 ইউ ইউনিক্স 0xffff8800a07da4c0 0t0 3435996 টাইপ = স্ট্রিম <-> 3435997 [এক্সর্গ, 3080, @ / টিএমপি / .এক্স 11-ইউনিক্স / এক্স0]

লিনাক্স -৩.৩ এর আগে

ইউনিক্স সকেট তথ্য পুনরুদ্ধার করতে পুরানো লিনাক্স এপিআই /proc/net/unixপাঠ্য ফাইলের মাধ্যমে । এটি সমস্ত ইউনিক্স ডোমেন সকেট (সকেটপেইস সহ) তালিকাভুক্ত করে। সেখানে প্রথম ক্ষেত্রটি (যদি সিসটেলkernel.kptr_restrict প্যারামিটারের সাথে অ- সুপারিউসারদের কাছে গোপন না থাকে ) যেমনটি @ টোটার ইতিমধ্যে ব্যাখ্যা করেছেন তাতে একটি unix_sockকাঠামোর কার্নেল ঠিকানা রয়েছে peerযা সংশ্লিষ্ট পিয়ারকে নির্দেশ করে একটি ক্ষেত্র ধারণ করে unix_sock। এছাড়া কি lsofজন্য আউটপুট DEVICEএকটি ইউনিক্স সকেট কলাম।

এখন সেই peerক্ষেত্রটির মান পাওয়ার অর্থ কার্নেল মেমরি পড়তে সক্ষম হওয়া এবং ঠিকানার peerসাথে সম্পর্কিত ক্ষেত্রটির অফসেট জানতে unix_sock

ইতিমধ্যে বেশ কয়েকটি gdbবেসড এবং- systemtapভিত্তিক সমাধান দেওয়া হয়েছে তবে চলমান কার্নেল ইনস্টল করার জন্য তাদের gdb/ systemtapএবং লিনাক্স কার্নেল ডিবাগ প্রতীকগুলি প্রয়োজন যা সাধারণত উত্পাদন সিস্টেমের ক্ষেত্রে হয় না।

অফসেটের হার্ডকডিং আসলে কোনও বিকল্প নয় কারণ কার্নেলের সংস্করণে এটি পরিবর্তিত হয়।

অফসেট নির্ধারণে এখন আমরা একটি বৈজ্ঞানিক পদ্ধতি ব্যবহার করতে পারি: আমাদের সরঞ্জামটি একটি ডামি তৈরি করুন socketpair(তারপরে আমরা উভয় সমবয়সীর ঠিকানা জানি) এবং অফসেটটি নির্ধারণ করতে অন্য প্রান্তে মেমরিটির চারপাশে পিয়ারের ঠিকানা অনুসন্ধান করুন ।

এখানে একটি প্রুফ-অফ কনসেপ্ট স্ক্রিপ্ট রয়েছে যা কেবল এটি ব্যবহার করে perl(i386 এ কার্নেলটি 2.4.27 এবং 2.6.32 সাফল্যের সাথে পরীক্ষিত হয়েছে) এবং amd64 এ 3.13 এবং 3.16। উপরের মত, এটি চারপাশে মোড়কের কাজ করে lsof:

উদাহরণ স্বরূপ:

$ যে-lsof-wrapper -aUc এনএম-অ্যাপলেট
কম্যান্ড পিআইডি ব্যবহারকারী এফডি টাইপ ডিভাইস সাইজ / কোনও নাম বাদ নেই
NM-অ্যাপলেট 4183 Stephane 4u UNIX 0xffff8800a055eb40 0t0 36888 টাইপ = STREAM -> 0xffff8800a055e7c0 [dbus,-ডেমন, 4190, @ / tmp / 'dbus,-AiBCXOnuP6] 
NM-অ্যাপলেট 4183 Stephane 7u UNIX 0xffff8800a055e440 0t0 36890 টাইপ = STREAM -> 0xffff8800a055e0c0 [উপলব্ধকারী Xorg, 3080, @ / টিএমপি / .এক্স 11-ইউনিক্স / এক্স0] 
এনএম-অ্যাপলেট 4183 স্টেফেন 8 ইউ ইউনিক্স 0xffff8800a05c1040 0t0 36201 টাইপ = স্ট্রিম -> 0xffff8800a05c13c0 [ডিবিএস-ডেমন, 4118, @ / টিএমপি / ডিবিএস-এএনএক্সএনসিআরএনএম 1 
এনএন 1 UNIX 0xffff8800a055d080 0t0 36219 টাইপ = STREAM -> 0xffff8800a055d400 [dbus,-ডেমন, 4118, @ / tmp / 'dbus,-yxxNr1NkYC] 
NM-অ্যাপলেট 4183 12u UNIX 0xffff88022e0dfb80 0t0 36221 টাইপ = STREAM Stephane -> 0xffff88022e0df800 [dbus,-ডেমন, 2268, / Var / চালানোর / dbus, / system_bus_socket]
এনএম-অ্যাপলেট 4183 স্টেফেন 13 ইউ ইউনিক্স 0xffff88022e0f80c0 0t0 37025 টাইপ = স্ট্রিম -> 0xffff88022e29ec00 [ডিবিস-ডেমন, 2268, / ভের / রান / ডিবিস / সিস্টেম_বাস_সকেট]

লিপিটি এখানে:

#! /usr/bin/perl
# wrapper around lsof to add peer information for Unix
# domain sockets. needs lsof, and superuser privileges.
# Copyright Stephane Chazelas 2015, public domain.
# example: sudo this-lsof-wrapper -aUc Xorg
use Socket;

open K, "<", "/proc/kcore" or die "open kcore: $!";
read K, $h, 8192 # should be more than enough
 or die "read kcore: $!";

# parse ELF header
my ($t,$o,$n) = unpack("x4Cx[C19L!]L!x[L!C8]S", $h);
$t = $t == 1 ? "L3x4Lx12" : "Lx4QQx8Qx16"; # program header ELF32 or ELF64
my @headers = unpack("x$o($t)$n",$h);

# read data from kcore at given address (obtaining file offset from ELF
# @headers)
sub readaddr {
  my @h = @headers;
  my ($addr, $length) = @_;
  my $offset;
  while (my ($t, $o, $v, $s) = splice @h, 0, 4) {
    if ($addr >= $v && $addr < $v + $s) {
      $offset = $o + $addr - $v;
      if ($addr + $length - $v > $s) {
        $length = $s - ($addr - $v);
      }
      last;
    }
  }
  return undef unless defined($offset);
  seek K, $offset, 0 or die "seek kcore: $!";
  my $ret;
  read K, $ret, $length or die "read($length) kcore \@$offset: $!";
  return $ret;
}

# create a dummy socketpair to try find the offset in the
# kernel structure
socketpair(Rdr, Wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
 or die "socketpair: $!";
$r = readlink("/proc/self/fd/" . fileno(Rdr)) or die "readlink Rdr: $!";
$r =~ /\[(\d+)/; $r = $1;
$w = readlink("/proc/self/fd/" . fileno(Wtr)) or die "readlink Wtr: $!";
$w =~ /\[(\d+)/; $w = $1;
# now $r and $w contain the socket inodes of both ends of the socketpair
die "Can't determine peer offset" unless $r && $w;

# get the inode->address mapping
open U, "<", "/proc/net/unix" or die "open unix: $!";
while (<U>) {
  if (/^([0-9a-f]+):(?:\s+\S+){5}\s+(\d+)/) {
    $addr{$2} = hex $1;
  }
}
close U;

die "Can't determine peer offset" unless $addr{$r} && $addr{$w};

# read 2048 bytes starting at the address of Rdr and hope to find
# the address of Wtr referenced somewhere in there.
$around = readaddr $addr{$r}, 2048;
my $offset = 0;
my $ptr_size = length(pack("L!",0));
my $found;
for (unpack("L!*", $around)) {
  if ($_ == $addr{$w}) {
    $found = 1;
    last;
  }
  $offset += $ptr_size;
}
die "Can't determine peer offset" unless $found;

my %peer;
# now retrieve peer for each socket
for my $inode (keys %addr) {
  $peer{$addr{$inode}} = unpack("L!", readaddr($addr{$inode}+$offset,$ptr_size));
}
close K;

# Now get info about processes tied to sockets using lsof
my (%fields, %proc);
open LSOF, '-|', 'lsof', '-nPUFpcfdn';
while (<LSOF>) {
  if (/(.)(.*)/) {
    $fields{$1} = $2;
    if ($1 eq 'n') {
      $proc{hex($fields{d})}->{"$fields{c},$fields{p}" .
      ($fields{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
    }
  }
}
close LSOF;

# and finally process the lsof output
open LSOF, '-|', 'lsof', @ARGV;
while (<LSOF>) {
  chomp;
  for my $addr (/0x[0-9a-f]+/g) {
    $addr = hex $addr;
    my $peer = $peer{$addr};
    if (defined($peer)) {
      $_ .= $peer ?
            sprintf(" -> 0x%x[", $peer) . join("|", keys%{$proc{$peer}}) . "]" :
            "[LISTENING]";
      last;
    }
  }
  print "$_\n";
}
close LSOF or exit(1);

1
@ মাইকজার্ভ, এটি সেই মন্তব্যে ফলোআপ । ইউনিক্স সকেটের অন্য প্রান্তটি সন্ধান না করা এমন একটি জিনিস যা সর্বদা আমাকে বিরক্ত করে তোলে (প্রায়শই এক্স ক্লায়েন্ট সন্ধান করার সময় এবং সে সম্পর্কে একটি সাম্প্রতিক প্রশ্ন ছিল )। আমি চেষ্টা করে দেখব সিডো-টার্মিনালগুলির জন্য অনুরূপ পদ্ধতির ব্যবহার করা যেতে পারে এবং সেগুলি lsofলেখককে প্রস্তাব করব।
স্টাফেন চেজেলাস

1
আমি এখনও বিশ্বাস করতে পারি না যে এটি কার্নেল দ্বারা সরবরাহ করা হয়নি! আমার সত্যিই কোনও প্যাচ জমা দেওয়া উচিত, যদি অন্য কিছু না হয় তবে এটি কেন ইতিমধ্যে বিদ্যমান নেই তা আবিষ্কার করা উচিত।
জোনাথন রাইনহার্ট

1
ssএটা কি করে না? এটি আমার মাথার উপরে একরকম, তবে ss -pxপিয়ারের তথ্যের সাথে প্রচুর ইউনিক্স সকেটের তালিকা রয়েছে: users: ("nacl_helper",pid=18992,fd=6),("chrome",pid=18987,fd=6),("chrome",pid=18975,fd=5)) u_str ESTAB\t0\t0\t/run/dbus/system_bus_socket 8760\t\t* 15068এবং কলামের শিরোনামগুলি State\tRecv-Q\tSend-Q\tLocal Address:Port\tPeer Address:Port
হ'ল

1
এছাড়াও, যদি আমি করি তবে আমি lsof -c terminologyদেখতে পাচ্ছি terminolo 12731\tmikeserv\t12u\tunix\t0xffff880600e82680\t0t0\t1312426\ttype=STREAMতবে আমি যদি তা পাই তবে ss -px | grep terminology:u_str\tESTAB\t0\t0\t* 1312426\t*1315046\tusers:(("terminology",pid=12731,fd=12))
মাইকসার্ভ

1
@ মাইকজার্ভস, দেখে মনে হচ্ছে এটি সত্যিই আছে! দেখে মনে হচ্ছে আমি ইদানীং প্রচুর সময় নষ্ট করছি ...
স্টাফেন চেজেলাস

9

এর্ক্কি সেপ্পালার আসলে একটি সরঞ্জাম রয়েছে যা লিনাক্স কার্নেল থেকে জিডিবি দিয়ে এই তথ্যটি উদ্ধার করে .. এটি এখানে উপলব্ধ ।


2
খুব দরকারী তথ্য! এমনকি যদি সরঞ্জামটি আমার জন্য বাক্সের বাইরে কাজ না করে (এটি একটি কার্নেল ওফস ঘটায়), ধারণাটি আমাকে অন্য প্রান্তটি সনাক্ত করতে সহায়তা করেছিল। আমি স্ট্যাক ওভারফ্লো সম্পর্কে আমার সমাধান বর্ণনা করেছি
এমভিজি

8

কার্নেল ৩.৩

আপনি এখন এই সাথে এই তথ্য পেতে পারেন :ss

# ss -xp

এখন আপনি Peerকলামে দেখতে পাবেন একটি আইডি (ইনোড নম্বর) যা Localকলামের অন্য আইডির সাথে সম্পর্কিত । ম্যাচিং আইডি হ'ল সকেটের দুটি প্রান্ত।

দ্রষ্টব্য: UNIX_DIAGবিকল্পটি আপনার কার্নেলের মধ্যে সক্ষম করা আবশ্যক।

কার্নেলের আগে ৩.৩

লিনাক্স ইউজারল্যান্ডে এই তথ্য প্রকাশ করে নি।

তবে, কার্নেল মেমরিটি দেখে আমরা এই তথ্যটি অ্যাক্সেস করতে পারি।

দ্রষ্টব্য: এই উত্তরটি ব্যবহার করে এটি করা হয় gdbতবে দয়া করে @ স্টাফেনচাজেলাসের উত্তরটি দেখুন যা এই বিষয়ে আরও বিস্তৃত।

# lsof | grep whatever
mysqld 14450 (...) unix 0xffff8801011e8280 (...) /var/run/mysqld/mysqld.sock
mysqld 14450 (...) unix 0xffff8801011e9600 (...) /var/run/mysqld/mysqld.sock

এখানে 2 টি বিভিন্ন সকেট, 1 শ্রবণ এবং 1 টি প্রতিষ্ঠিত। হেক্সা নম্বরটি সংশ্লিষ্ট কার্নেল unix_sockকাঠামোরpeer ঠিকানা, সকেটের অন্য প্রান্তের একটি বৈশিষ্ট্য (একটি unix_sockকাঠামোর উদাহরণ )ও রয়েছে attrib

এখন আমরা কার্নেল মেমরির মধ্যে gdbসন্ধান করতে ব্যবহার করতে পারি peer:

# gdb /usr/lib/debug/boot/vmlinux-3.2.0-4-amd64 /proc/kcore
(gdb) print ((struct unix_sock*)0xffff8801011e9600)->peer
$1 = (struct sock *) 0xffff880171f078c0

# lsof | grep 0xffff880171f078c0
mysql 14815 (...) unix 0xffff880171f078c0 (...) socket

আপনি এখানে যান, সকেটের অপর mysqlপ্রান্তটি পিআইডি 14815 দ্বারা ধারণ করে ।

আপনার কার্নেলটি অবশ্যই KCORE_ELFব্যবহারের সাথে সংকলিত হতে হবে /proc/kcore। এছাড়াও, আপনার ডিবাগিং প্রতীক সহ আপনার কার্নেল চিত্রের একটি সংস্করণ প্রয়োজন। ডেবিয়ান 7-তে, apt-get install linux-image-3.2.0-4-amd64-dbgএই ফাইলটি সরবরাহ করবে।

ডিবাজিযোগ্য কার্নেল চিত্রের প্রয়োজন নেই ...

যদি আপনার সিস্টেমে ডিবাগিং কার্নেল চিত্র না থাকে (বা রাখতে চান না), আপনি মানটিকে gdb"ম্যানুয়ালি" অ্যাক্সেসের জন্য অফসেট মেমরিটি দিতে পারেন peer। এই অফসেট মানটি সাধারণত কার্নেল সংস্করণ বা আর্কিটেকচারের সাথে পৃথক হয়।

আমার কার্নেলে, আমি জানি অফসেটটি 680 বাইট, এটি 85 গুণ .৪ বিট। সুতরাং আমি এটি করতে পারি:

# gdb /boot/vmlinux-3.2.0-4-amd64 /proc/kcore
(gdb) print ((void**)0xffff8801011e9600)[85]
$1 = (void *) 0xffff880171f078c0

ভয়েল, উপরের মত একই ফলাফল।

আপনার যদি একই মেশিনে একই কার্নেল চলমান থাকে তবে এই বৈকল্পিকটি ব্যবহার করা আরও সহজ কারণ আপনার কেবলমাত্র অফসেট মানটি ডিবাগ চিত্রের প্রয়োজন নেই।

প্রথমে (সহজেই) এই অফসেট মানটি আবিষ্কার করতে আপনার ডিবাগ চিত্রটি দরকার:

$ pahole -C unix_sock /usr/lib/debug/boot/vmlinux-3.2.0-4-amd64
struct unix_sock {
  (...)
  struct sock *              peer;                 /*   680     8 */
  (...)
}

আপনি এখানে 680 বাইট যান, এটি 85 x 64 বিট বা 170 x 32 বিট।

এই উত্তরের বেশিরভাগ কৃতিত্ব এমভিজির কাছে যায় ।


2
অফসেটটি পুনরুদ্ধার করার জন্য আরেকটি পদ্ধতি হ'ল সকেটপেইর তৈরি করা / / প্রোক / নেট / ইউনিক্সের ইনড সংখ্যার উপর ভিত্তি করে / প্রো / পিআইএফ / এফডি / * এর পাঠ্যসূচিগুলি সনাক্ত করে এবং একটি সকেটের ঠিকানার কাছাকাছি মেমরি স্ক্যান করা to অন্যের ঠিকানা। এটি যুক্তিসঙ্গতভাবে বহনযোগ্য (সম্পূর্ণ লিনাক্স সংস্করণ এবং আর্কিটেকচার) তৈরি করতে পারে যা lsof দ্বারা প্রয়োগ করা যেতে পারে। আমি একটি পিসি নিয়ে আসার চেষ্টা করব।
স্টাফেন চেজেলাস

2
আমি এখন এমন একটি পিসিও যুক্ত করেছি যা দেখেছি আমি পরীক্ষিত সিস্টেমগুলিতে ভাল কাজ করে।
স্টাফেন চেজেলাস

5

এই সমাধানটি কাজ করা হলেও সীমিত আগ্রহের কারণ আপনার যদি সাম্প্রতিক পর্যায়ে পর্যাপ্ত সিস্টেমট্যাপ থাকে তবে আপনার কাছে সাম্প্রতিক পর্যায়ে যথেষ্ট কার্নেল থাকবে যেখানে আপনি ssভিত্তিক পদ্ধতির ব্যবহার করতে পারেন এবং যদি আপনি কোনও পুরানো কার্নেলের উপর থাকেন তবে এটি অন্য সমাধান , যদিও আরও বেশি হ্যাকি কাজ করার সম্ভাবনা বেশি এবং সংযোজন সফ্টওয়্যার প্রয়োজন হয় না।

systemtapএই ধরণের কাজের জন্য কীভাবে ব্যবহার করা যায় তার একটি প্রদর্শন হিসাবে এখনও কার্যকর ।

যদি একটি সাম্প্রতিক লিনাক্স সিস্টেমে একটি ওয়ার্কিং সিস্টেমট্যাপ (1.8 বা আরও নতুন) থাকে তবে আপনি আউটপুট পোস্ট-প্রক্রিয়া করতে নীচের স্ক্রিপ্টটি ব্যবহার করতে পারেন lsof:

উদাহরণ স্বরূপ:

s lsof -aUc nm-applet | sudo যে স্ক্রিপ্ট
কম্যান্ড পিআইডি ব্যবহারকারী এফডি টাইপ ডিভাইস সাইজ / কোনও নাম বাদ নেই
NM-অ্যাপলেট 4183 Stephane 4u UNIX 0xffff8800a055eb40 0t0 36888 টাইপ = STREAM -> 0xffff8800a055e7c0 [dbus,-ডেমন, 4190, @ / tmp / 'dbus,-AiBCXOnuP6] 
NM-অ্যাপলেট 4183 Stephane 7u UNIX 0xffff8800a055e440 0t0 36890 টাইপ = STREAM -> 0xffff8800a055e0c0 [উপলব্ধকারী Xorg, 3080, @ / টিএমপি / .এক্স 11-ইউনিক্স / এক্স0] 
এনএম-অ্যাপলেট 4183 স্টেফেন 8 ইউ ইউনিক্স 0xffff8800a05c1040 0t0 36201 টাইপ = স্ট্রিম -> 0xffff8800a05c13c0 [ডিবিএস-ডেমন, 4118, @ / টিএমপি / ডিবিএস-এএনএক্সএনসিআরএনএম 1 
এনএন 1 UNIX 0xffff8800a055d080 0t0 36219 টাইপ = STREAM -> 0xffff8800a055d400 [dbus,-ডেমন, 4118, @ / tmp / 'dbus,-yxxNr1NkYC] 
NM-অ্যাপলেট 4183 12u UNIX 0xffff88022e0dfb80 0t0 36221 টাইপ = STREAM Stephane -> 0xffff88022e0df800 [dbus,-ডেমন, 2268, / Var / চালানোর / dbus, / system_bus_socket]
এনএম-অ্যাপলেট 4183 স্টেফেন 13 ইউ ইউনিক্স 0xffff88022e0f80c0 0t0 37025 টাইপ = স্ট্রিম -> 0xffff88022e29ec00 [ডিবিস-ডেমন, 2268, / ভের / রান / ডিবিস / সিস্টেম_বাস_সকেট]

(যদি আপনি 0xffff এর পরিবর্তে 0x000000000000000000 দেখতে পান ..., কারণ এটি kernel.kptr_restrictআপনার সিস্টেমে সিসটেল প্যারামিটার সেট করা আছে যার ফলে কার্নেল পয়েন্টারগুলি অ-সুযোগ- সুবিধাযুক্ত প্রক্রিয়াগুলি থেকে গোপন করা হয় , এক্ষেত্রে আপনাকে lsofরুট হিসাবে চালানোর প্রয়োজন হবে অর্থপূর্ণ ফলাফল)।

এই স্ক্রিপ্টটি নিউলাইন চরিত্রগুলির সাথে সকেট ফাইলের নামগুলির সাথে লড়াই করার কোনও চেষ্টা করে না, তবে তাও হয় না lsof( lsofফাঁকা বা কোলোনগুলিও মানায় না)।

systemtapএখানে কার্নেলের সমস্ত unix_sockকাঠামোর ঠিকানা এবং পিয়ারের ঠিকানা ডাম্প করতে ব্যবহৃত হয় unix_socket_table

কেবলমাত্র লিনাক্সে 3.16 amd64 এ সিস্টেমট্যাপ 2.6 এবং 3.13 দিয়ে 3.13 পরীক্ষা করা হয়েছে।

#! /usr/bin/perl
# meant to process lsof output to try and find the peer of a given
# unix domain socket. Needs a working systemtap, lsof, and superuser
# privileges. Copyright Stephane Chazelas 2015, public domain.
# Example: lsof -aUc X | sudo this-script
open STAP, '-|', 'stap', '-e', q{
  probe begin {
    offset = &@cast(0, "struct sock")->__sk_common->skc_node;
    for (i = 0; i < 512; i++) 
      for (p = @var("unix_socket_table@net/unix/af_unix.c")[i]->first;
           p;
           p=@cast(p, "struct hlist_node")->next
          ) {
        sock = p - offset;
        printf("%p %p\n", sock, @cast(sock, "struct unix_sock")->peer);
    }
    exit()
  }
};  
my %peer;
while (<STAP>) {
  chomp;
  my ($a, $b) = split;
  $peer{$a} = $b;
}
close STAP;

my %f, %addr;
open LSOF, '-|', 'lsof', '-nPUFpcfdn';
while (<LSOF>) {
  if (/(.)(.*)/) {
    $f{$1} = $2;
    if ($1 eq 'n') {
      $addr{$f{d}}->{"$f{c},$f{p}" . ($f{n} =~ m{^([@/].*?)( type=\w+)?$} ? ",$1" : "")} = "";
    }
  }
}
close LSOF;

while (<>) {
  chomp;
  for my $addr (/0x[0-9a-f]+/g) {
    my $peer = $peer{$addr};
    if (defined($peer)) {
      $_ .= $peer eq '0x0' ?
            "[LISTENING]" :
            " -> $peer\[" . join("|", keys%{$addr{$peer}}) . "]";
      last;
    }
  }
  print "$_\n";
}

parse error: unknown statistic operator @var: আমি কিছু অনুপস্থিত করছি?
টোটার

@ টোটারকে সিস্টেমট্যাপ @var১.৮, ২০১২-০-17-১ ( এ যুক্ত করা হয়েছে (সর্বশেষতম ২.7)
স্টাফেন চেজেলাস

2

এলএসফের ৪.৯৯৯ শেষের পয়েন্ট বিকল্পগুলি প্রদর্শন করে।

Lsof.8 থেকে উদ্ধৃত:

+|-E +E specifies that process intercommunication channels should be
     displayed with endpoint information and the channels
     of the endpoints should also be displayed.  Currently
     only pipe on Linux is implemented.

     Endpoint information is displayed in the NAME column
     in the form "PID,cmd,FDmode".  PID is the endpoint
     process ID; cmd is the endpoint process command; FD is
     the endpoint file's descriptor; and mode is the
     endpoint file's access mode.  Multiple occurrences of
     this information can appear in a file's NAME column.

     -E specfies that Linux pipe files should only be
     displayed with endpoint information.

আউটপুট উদাহরণ:

mozStorag 21535 22254  yamato    6u     unix 0xf...       0t0     348924 type=STREAM pino=351122 4249,dbus-daem,55u
mozStorag 21535 22254  yamato   10u     unix 0xf...       0t0     356193 type=STREAM pino=356194 21535,gdbus,11u
mozStorag 21535 22254  yamato   11u     unix 0xf...       0t0     356194 type=STREAM pino=356193 21535,gdbus,10u
mozStorag 21535 22254  yamato   21u     unix 0xf...       0t0     355141 type=STREAM pino=357544 4249,dbus-daem,60u
mozStorag 21535 22254  yamato   26u     unix 0xf...       0t0     351134 type=STREAM pino=355142 5015,gdbus,17u
mozStorag 21535 22254  yamato   69u     unix 0xf...       0t0     469354 type=STREAM pino=468160 4545,alsa-sink,21u
mozStorag 21535 22254  yamato   82u     unix 0xf...       0t0     449383 type=STREAM pino=449384 12257,Chrome_Ch,3u
mozStorag 21535 22254  yamato   86u     unix 0xf...       0t0     355174 type=SEQPACKET pino=355175 21535,gdbus,95u
mozStorag 21535 22254  yamato   95u     unix 0xf...       0t0     355175 type=SEQPACKET pino=355174 21535,gdbus,86u 12257,Chrome_Ch,4u
mozStorag 21535 22254  yamato  100u     unix 0xf...       0t0     449389 type=STREAM pino=456453 3614,Xorg,38u
mozStorag 21535 22254  yamato  105u     unix 0xf...       0t0     582613 type=STREAM pino=586261
obexd     22163        yamato    1u     unix 0xf...       0t0     361859 type=STREAM pino=365931
obexd     22163        yamato    2u     unix 0xf...       0t0     361860 type=STREAM pino=365934
obexd     22163        yamato    3u     unix 0xf...       0t0     361241 type=DGRAM pino=10028
obexd     22163        yamato    6u     unix 0xf...       0t0     361242 type=STREAM pino=361864 4249,dbus-daem,70u

2

যেহেতু লিনাক্স কার্নেল ৪.২ রয়েছে CONFIG_UNIX_DIAG, এটি ইউএনআইএক্স ডোমেন সকেট সম্পর্কিত অতিরিক্ত তথ্য সরবরাহ করে, Virtual File System(ভিএফএস) তথ্য, যাতে প্রক্রিয়াটির পথে পাথ থেকে ইনোডকে সংযুক্ত করার জন্য এখন পর্যন্ত হারিয়ে যাওয়া তথ্য রয়েছে। এটি ইতিমধ্যে আইপ্রেট 2ss থেকে টুলটি ব্যবহার করে v4.19.0 ~ 55 সংস্করণ দিয়ে শুরু করা যেতে পারে :

$ ss --processes --unix --all --extened
...
Netid  State   Recv-Q  Send-Q  Local Address:Port      Peer Address:Port
u_str  LISTEN  0       5         /tmp/socket 13381347             * 0     users:(("nc",pid=12550,fd=3)) <-> ino:1569897 dev:0/65025 peers:

ডিভাইস নম্বর এবং পথ ইনোড থেকে আপনি পেতে পারেন

$ stat -c 'ino:%i dev:0/%d' /tmp/socket
ino:1569946 dev:0/65025

ss ফিল্টারিং সমর্থন করে:

 ss --processes --unix --all --extended 'sport = /tmp/socket'

তবে দয়া করে সচেতন হন যে এটি আপনার পক্ষে সঠিক সকেটটি তালিকাভুক্ত করতে পারে না, কারণ কোনও খারাপ প্রক্রিয়া আপনার মূল সকেটটির নাম পরিবর্তন করতে পারে এবং এটির পরিবর্তে এটির নিজের মন্দটিকে প্রতিস্থাপন করতে পারে:

mv /tmp/socket /tmp/socket.orig
nc -U -l /tmp/socket.evil &
mv /tmp/socket.evil /tmp/socket

lsof /tmp/socket, fuser /tmp/socketএবং ss --processes --unix --all --extended 'sport = /tmp/socket'সব মূল প্রক্রিয়া, তালিকা প্রস্তুত করা যাবে না মন্দ প্রতিস্থাপন। পরিবর্তে এই জাতীয় কিছু ব্যবহার করুন:

id=$(stat -c 'ino:%i dev:0/%d' /tmp/socket)
ss --processes --unix --all --extended | grep -F "$id"

অথবা ম্যান 7 সোক_ডায়াগে থাকা টেম্পলেটটির ভিত্তিতে আপনার নিজের লিট প্রোগ্রাম লিখুন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.