आइए मिलकर एक प्रोजेक्ट बनाएं!
लिनक्स उपकरण जैसे ps
, top
&netstat
महान हैं।
वे आपको इस बारे में बहुत सारी जानकारी देते हैं कि आपके सिस्टम में क्या हो रहा है।
- लेकिन वे कैसे काम करते हैं?
- उन्हें अपनी सारी जानकारी कहाँ से मिलती है?
- हम इसका उपयोग अपने स्वयं के टूल बनाने के लिए कैसे कर सकते हैं?
इस पोस्ट में हम तीन लोकप्रिय Linux टूल को एक साथ फिर से बनाएंगे।
आप एक 2×1 भोजन प्राप्त करने जा रहे हैं, कुछ रूबी ट्रिक्स सीखें और एक ही समय में उपयोगी लिनक्स ज्ञान प्राप्त करें!
स्थिति की जानकारी ढूँढना
तो आइए इस सवाल का जवाब देने की कोशिश करें कि ये सभी टूल अपनी जानकारी कहां से ढूंढते हैं।
उत्तर proc फाइल सिस्टम में है!
अगर आप /proc
के अंदर देखें तो निर्देशिका यह आपके कंप्यूटर पर किसी भी अन्य निर्देशिका की तरह निर्देशिकाओं और फ़ाइलों के एक समूह की तरह दिखाई देगी।
ये वास्तविक फ़ाइलें नहीं हैं, यह Linux कर्नेल के लिए उपयोगकर्ताओं को डेटा दिखाने का एक तरीका है।
यह बहुत सुविधाजनक है क्योंकि उन्हें सामान्य फ़ाइलों की तरह माना जा सकता है, जिसका अर्थ है कि आप उन्हें बिना किसी विशेष टूल के पढ़ सकते हैं।
Linux की दुनिया में बहुत सी चीज़ें इस तरह काम करती हैं.
यदि आप एक और उदाहरण देखना चाहते हैं तो /dev
. पर एक नज़र डालें निर्देशिका।
अब जब हम समझ गए हैं कि हम किसके साथ काम कर रहे हैं, तो आइए /proc
की सामग्री पर एक नज़र डालते हैं। निर्देशिका…
1 10 104 105 11 11015 11469 11474 11552 11655
यह सिर्फ एक छोटा सा नमूना है, लेकिन आप जल्दी से एक पैटर्न देख सकते हैं।
वे सभी नंबर क्या हैं?
खैर, यह पता चला है कि ये पीआईडी (प्रोसेस आईडी) हैं।
प्रत्येक प्रविष्टि में एक विशिष्ट प्रक्रिया के बारे में जानकारी होती है।
अगर आप ps
चलाते हैं आप देख सकते हैं कि कैसे हर प्रक्रिया से एक पीआईडी जुड़ा होता है:
PID TTY TIME CMD 15952 pts/5 00:00:00 ps 22698 pts/5 00:00:01 bash
इससे हम यह निष्कर्ष निकाल सकते हैं कि ps जो करता है वह /proc
. पर बस पुनरावृति है निर्देशिका और उसे मिलने वाली जानकारी को प्रिंट करें।
आइए देखें कि उन क्रमांकित निर्देशिकाओं में से एक के अंदर क्या है:
attr autogroup auxv cgroup clear_refs cmdline comm cpuset cwd environ exe fd
यह जगह बचाने के लिए सिर्फ एक नमूना है, लेकिन मैं आपको पूरी सूची देखने के लिए प्रोत्साहित करता हूं।
यहां कुछ रोचक प्रविष्टियां दी गई हैं :
Entry | विवरण |
---|---|
comm | कार्यक्रम का नाम |
cmdline | इस प्रक्रिया को शुरू करने के लिए प्रयुक्त कमांड |
पर्यावरण | पर्यावरण चर जिनके साथ यह प्रक्रिया शुरू की गई थी |
स्थिति | प्रक्रिया स्थिति (चल रहा है, सो रहा है...) और स्मृति उपयोग |
fd | निर्देशिका जिसमें फ़ाइल डिस्क्रिप्टर शामिल हैं (खुली फ़ाइलें, सॉकेट...) |
अब जब हम यह जान गए हैं तो हमें कुछ टूल लिखना शुरू करने में सक्षम होना चाहिए!
चल रहे कार्यक्रमों को कैसे सूचीबद्ध करें
आइए केवल /proc
. के अंतर्गत सभी निर्देशिकाओं की सूची प्राप्त करके प्रारंभ करें ।
हम Dir
. का उपयोग करके ऐसा कर सकते हैं कक्षा।
उदाहरण :
Dir.glob("/proc/[0-9]*")
ध्यान दें कि मैंने एक संख्या श्रेणी का उपयोग कैसे किया, इसका कारण यह है कि /proc
. के अंतर्गत अन्य फ़ाइलें हैं कि हम अभी इसकी परवाह नहीं करते हैं, हम केवल क्रमांकित निर्देशिका चाहते हैं।
अब हम इस सूची पर पुनरावृति कर सकते हैं और दो कॉलम प्रिंट कर सकते हैं, एक पीआईडी के साथ और दूसरा प्रोग्राम नाम के साथ।
उदाहरण :
pids = Dir.glob("/proc/[0-9]*") puts "PID\tCMD" puts "-" * 15 pids.each do |pid| cmd = File.read(pid + "/comm") pid = pid.scan(/\d+/).first puts "#{pid}\t#{cmd}" endडालता है
और यह आउटपुट है :
PID CMD --------------- 1 systemd 2 kthreadd 3 ksoftirqd/0 5 kworker/0 7 migration/0 8 rcu_preempt 9 rcu_bh 10 rcu_sched
अरे, ऐसा लगता है कि हमने अभी-अभी ps
. बनाया है ! हाँ, यह मूल से सभी फैंसी विकल्पों का समर्थन नहीं करता है, लेकिन हमने कुछ काम किया है।
कौन सुन रहा है?
आइए netstat
को दोहराने की कोशिश करें अब, यह आउटपुट जैसा दिखता है (-ant
. के साथ) झंडे के रूप में)।
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN tcp 0 0 192.168.1.82:39530 182.14.172.159:22 ESTABLISHED
हमें यह जानकारी कहां मिल सकती है? अगर आपने कहा “अंदर /proc
" आप ठीक कह रहे हैं! अधिक विशिष्ट होने के लिए आप इसे /proc/net/tcp
. में पा सकते हैं ।
लेकिन एक छोटी सी समस्या है, यह netstat
. जैसा कुछ नहीं दिखता है आउटपुट!
0: 0100007F:1538 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1001 0 9216 1: 2E58A8C0:9A6A 9FBB0EB9:0016 01 00000000:00000000 00:00000000 00000000 1000 0 258603
इसका मतलब यह है कि हमें नियमित अभिव्यक्तियों के साथ कुछ विश्लेषण करने की आवश्यकता है। अभी के लिए बस स्थानीय पते और स्थिति की चिंता करें।
यहां वह रेगेक्स है जिसके साथ मैं आया था :
LINE_REGEX = /\s+\d+: (?<local_addr>\w+):(?<local_port>\w+) \w+:\w+ (?<status>\w+)/
यह हमें कुछ हेक्साडेसिमल मान देगा जिन्हें हमें दशमलव में बदलने की आवश्यकता है। आइए एक ऐसा वर्ग बनाएं जो हमारे लिए ऐसा करेगा।
class TCPInfo def initialize(line) @data = parse(line) end def parse(line) line.match(LINE_REGEX) end def local_port @data["local_port"].to_i(16) end # Convert hex to regular IP notation def local_addr decimal_to_ip(@data["local_addr"].to_i(16)) end STATUSES = { "0A" => "LISTENING", "01" => "ESTABLISHED", "06" => "TIME_WAIT", "08" => "CLOSE_WAIT" } def status code = @data["status"] STATUSES.fetch(code, "UNKNOWN") end # Don't worry too much about this. It's some binary math. def decimal_to_ip(decimal) ip = [] ip << (decimal >> 24 & 0xFF) ip << (decimal >> 16 & 0xFF) ip << (decimal >> 8 & 0xFF) ip << (decimal & 0xFF) ip.join(".") end end
परिणामों को एक सुंदर तालिका प्रारूप में प्रिंट करने के लिए केवल एक चीज बची है।
require 'table_print' tp connections
उदाहरण आउटपुट :
STATUS | LOCAL_PORT | LOCAL_ADDR ------------|------------|-------------- LISTENING | 5432 | 127.0.0.1 ESTABLISHED | 39530 | 192.168.88.46
हाँ, यह रत्न कमाल का है!
मुझे अभी इसके बारे में पता चला है और ऐसा लगता है कि मुझे ljust
. के साथ खिलवाड़ नहीं करना पड़ेगा / rjust
फिर से
मेरे पोर्ट का उपयोग करना बंद करें!
क्या आपने कभी यह संदेश देखा है?
Address already in use - bind(2) for "localhost" port 5000
उम्म…
मुझे आश्चर्य है कि कौन सा प्रोग्राम उस पोर्ट का उपयोग कर रहा है।
आइए पता करें :
fuser -n tcp -v 5000 PORT USER PID ACCESS CMD 5000/tcp rubyguides 30893 F.... nc
आह, तो हमारा अपराधी है!
अब हम इस कार्यक्रम को रोक सकते हैं यदि हम इसे नहीं चलाना चाहते हैं और यह हमारे बंदरगाह को मुक्त कर देगा। "फ्यूज़र" प्रोग्राम को कैसे पता चला कि इस पोर्ट का उपयोग कौन कर रहा है?
आपने अनुमान लगाया!
/proc
फाइल सिस्टम फिर से।
वास्तव में, यह दो चीजों को जोड़ती है जिन्हें हमने पहले ही कवर कर लिया है:प्रक्रिया सूची के माध्यम से चलना और /proc/net/tcp
से सक्रिय कनेक्शन पढ़ना ।
हमें बस एक अतिरिक्त कदम चाहिए :
ओपन पोर्ट की जानकारी को PID से मिलाने का तरीका खोजें।
यदि हम TCP डेटा को देखें जो हमें /proc/net/tcp
से मिल सकता है , पीआईडी वहाँ नहीं है। लेकिन हम इनोड नंबर का उपयोग कर सकते हैं।
"इनोड एक डेटा संरचना है जिसका उपयोग फाइल सिस्टम ऑब्जेक्ट का प्रतिनिधित्व करने के लिए किया जाता है।" - विकिपीडिया
मिलान प्रक्रिया को खोजने के लिए हम इनोड का उपयोग कैसे कर सकते हैं? अगर हम fd
. के अंतर्गत देखें एक प्रक्रिया की निर्देशिका जिसे हम जानते हैं कि एक खुला बंदरगाह है, हमें इस तरह की एक पंक्ति मिलेगी:
/proc/3295/fd/5 -> socket:[12345]
कोष्ठक के बीच की संख्या इनोड संख्या है। तो अब हमें बस इतना करना है कि सभी फाइलों पर पुनरावृति करें और हम मिलान प्रक्रिया को खोज लेंगे।
ऐसा करने का एक तरीका यहां दिया गया है :
x = Dir.glob("/proc/[0-9]*/fd/*").find do |fd| File.readlink(fd).include? "socket:[#{socket_inode}]" rescue nil end pid = x.scan(/\d+/).first name = File.readlink("/proc/#{pid}/exe") puts "Port #{hex_port.to_i(16)} in use by #{name} (#{pid})"
उदाहरण आउटपुट:
Port 5432 in use by /usr/bin/postgres (474)
कृपया ध्यान दें कि आपको इस कोड को रूट या प्रक्रिया स्वामी के रूप में चलाने की आवश्यकता होगी।
अन्यथा आप /proc
. के अंदर प्रक्रिया विवरण नहीं पढ़ पाएंगे ।
निष्कर्ष
इस पोस्ट में आपने सीखा कि लिनक्स वर्चुअल /proc
. के माध्यम से बहुत सारे डेटा को उजागर करता है फाइल सिस्टम। आपने /proc
के तहत डेटा का उपयोग करके ps, netstat और fuser जैसे लोकप्रिय Linux टूल को फिर से बनाने का तरीका भी सीखा। ।
नीचे दिए गए न्यूज़लेटर की सदस्यता लेना न भूलें ताकि आप अगली पोस्ट को याद न करें।