
ps उपयोगिता, eBPF मोड़ और कंटेनर संदर्भ के साथ
psc (ps container) एक तेज़ प्रक्रिया स्कैनर है जो सिस्टम स्थिति को सटीकता और पूर्ण कंटेनर संदर्भ के साथ क्वेरी करने के लिए eBPF इटरेटर और Google CEL का उपयोग करता है।
psc कर्नेल डेटा संरचनाओं से सीधे प्रक्रिया और फ़ाइल डिस्क्रिप्टर जानकारी पढ़ने के लिए eBPF इटरेटर का उपयोग करता है। यह दृष्टिकोण है:
/proc के माध्यम से उजागर नहीं होती है। मैं उन्नत उपयोग के लिए मांग पर task_struct के कुछ फ़ील्ड्स तक पहुँचने का एक तरीका जोड़ने की भी योजना बना रहा हूँ, लेकिन यह केवल एक विचार है/proc फ़ाइल सिस्टम को पूरी तरह से बायपास करता है, जो ऐसी दृश्यता प्रदान करता है जिसे यूज़रलैंड रूटकिट या LD_PRELOAD ट्रिक्स द्वारा कमजोर नहीं किया जा सकतापारंपरिक लिनक्स उपकरण जैसे ps, lsof, और ss शक्तिशाली लेकिन अनम्य हैं। वे निश्चित प्रारूप आउटपुट करते हैं जिनके लिए grep, awk, और sed के माध्यम से व्यापक पाइपिंग की आवश्यकता होती है:
# पारंपरिक: nginx प्रक्रियाएँ ढूँढें जो root के स्वामित्व में हैं
ps aux | grep nginx | grep root | grep -v grep
# psc: वही व्यक्त करें जो आपका मतलब है
psc 'process.name == "nginx" && process.user == "root"'
# पारंपरिक: पोर्ट 443 पर स्थापित कनेक्शन वाली प्रक्रियाएँ ढूँढें
ss -tnp | grep ESTAB | grep :443 | awk '{print $6}' | cut -d'"' -f2
# psc: एक स्पष्ट अभिव्यक्ति
psc 'socket.state == established && socket.dstPort == 443'
psc प्रक्रियाओं को फ़िल्टर करने के लिए Common Expression Language (CEL) का उपयोग करता है। CEL अभिव्यक्तियाँ लगभग प्राकृतिक भाषा की तरह पढ़ी जाती हैं, जो आपकी स्क्रिप्ट को स्व-दस्तावेजीकरण और रखरखाव योग्य बनाती हैं। अब grep | awk | sed | xargs की जटिल पाइपलाइनों को डिकोड करने की आवश्यकता नहीं है।
-o फ़्लैग आपको वही फ़ील्ड्स आउटपुट करने देता है जिनकी आपको आवश्यकता है, जो पोस्ट-प्रोसेसिंग को पूरी तरह से समाप्त कर देता है:
psc 'socket.state == listen' -o process.name,socket.srcPort
सामान्य जानकारी को जल्दी से प्रिंट करने के लिए आउटपुट प्रीसेट भी उपलब्ध हैं:
psc 'socket.type == tcp && socket.dstPort == 443' -o sockets
पारंपरिक उपकरणों में कंटेनरों की कोई अवधारणा नहीं होती है। कंटेनर जानकारी प्राप्त करने के लिए cgroup पथों को पार्स करना, कंटेनर रनटाइम को क्वेरी करना, और PID को मैन्युअल रूप से सहसंबंधित करना आवश्यक होता है:
# पारंपरिक: कंटेनरीकृत प्रक्रियाएँ ढूँढें (नाजुक, अपूर्ण)
ps aux | xargs -I{} sh -c 'cat /proc/{}/cgroup 2>/dev/null | grep -q docker && echo {}'
# psc: मूल कंटेनर समर्थन
psc 'container.runtime == docker'
psc स्वचालित रूप से Docker, containerd, CRI-O, और Podman के लिए कंटेनर संदर्भ (ID, नाम, इमेज, रनटाइम, लेबल) निकालता है। किसी भी कंटेनर की प्रक्रियाओं, फ़ाइलों और नेटवर्क कनेक्शनों को सीधे होस्ट से डीबग करें:
# किसी विशिष्ट कंटेनर में सभी प्रक्रियाएँ दिखाएँ
psc 'container.name == "my-app"' --tree
# root के रूप में चलने वाले कंटेनर ढूँढें
psc 'container.runtime == docker && process.user == "root"'
# अपने इमेज के साथ कंटेनरों की सूची बनाएँ
psc 'container.id != ""' -o process.pid,process.name,container.name,container.image
Debian/Ubuntu पर:
sudo apt-get install clang llvm libbpf-dev linux-headers-$(uname -r) linux-tools-$(uname -r)
Fedora/RHEL पर:
sudo dnf install clang llvm libbpf-devel kernel-devel bpftool
# vmlinux.h उत्पन्न करें (प्रति कर्नेल संस्करण एक बार आवश्यक)
make vmlinux
# बाइनरी बनाएँ
make build
या मैन्युअल रूप से:
bpftool btf dump file /sys/kernel/btf/vmlinux format c > bpf/vmlinux.h
go generate ./...
go build -o psc
sudo make install
eBPF प्रोग्राम लोड करने के लिए psc को रूट विशेषाधिकार की आवश्यकता होती है।
# सभी प्रक्रियाओं की सूची बनाएँ
sudo psc
# सभी प्रक्रियाओं को एक पेड़ के रूप में सूचीबद्ध करें
sudo psc --tree
प्रक्रियाओं को फ़िल्टर करने के लिए पहले तर्क के रूप में एक CEL अभिव्यक्ति पास करें:
# प्रक्रिया नाम से फ़िल्टर करें
psc 'process.name == "nginx"'
# उपयोगकर्ता द्वारा फ़िल्टर करें
psc 'process.user == "root"'
# कमांड लाइन सामग्री द्वारा फ़िल्टर करें
psc 'process.cmdline.contains("--config")'
# PID रेंज द्वारा फ़िल्टर करें
psc 'process.pid > 1000 && process.pid < 2000'
# शर्तों को संयोजित करें
psc 'process.name == "bash" || process.name == "zsh"'
# केवल कंटेनरीकृत प्रक्रियाएँ दिखाएँ
psc 'container.id != ""'
# कंटेनर रनटाइम द्वारा फ़िल्टर करें (स्थिरांक: docker, containerd, crio, podman)
psc 'container.runtime == docker'
# कंटेनर नाम द्वारा फ़िल्टर करें
psc 'container.name == "nginx"'
# कंटेनर इमेज द्वारा फ़िल्टर करें
psc 'container.image.contains("nginx:latest")'
# कंटेनर प्रक्रिया पदानुक्रम देखने के लिए पेड़ के रूप में दिखाएँ
psc 'container.runtime == docker' --tree
यह समझना कि कोई प्रक्रिया क्यों मौजूद है, अक्सर उसके खुले फ़ाइल डिस्क्रिप्टर और नेटवर्क कनेक्शन को देखने की आवश्यकता होती है:
# सुनने वाले TCP सॉकेट वाली प्रक्रियाएँ ढूँढें
psc 'socket.type == tcp && socket.state == listen'
# स्थापित कनेक्शन वाली प्रक्रियाएँ ढूँढें
psc 'socket.state == established'
# किसी विशिष्ट पोर्ट से जुड़ी प्रक्रियाएँ ढूँढें
psc 'socket.dstPort == 443'
# Unix सॉकेट का उपयोग करने वाली प्रक्रियाएँ ढूँढें
psc 'socket.family == unix'
# /etc में खुली फ़ाइलों वाली प्रक्रियाएँ ढूँढें
psc 'file.path.startsWith("/etc")'
प्रक्रिया फ़ील्ड्स (process.X):
name - प्रक्रिया का नाम (स्ट्रिंग)pid - प्रक्रिया ID (int)ppid - मूल प्रक्रिया ID (int)tid - थ्रेड ID (int)euid - प्रभावी उपयोगकर्ता ID (int)ruid - वास्तविक उपयोगकर्ता ID (int)suid - सहेजा गया सेट-उपयोगकर्ता-ID (int)user - उपयोगकर्ता नाम (स्ट्रिंग)cmdline - पूर्ण कमांड लाइन (स्ट्रिंग)state - प्रक्रिया स्थिति (uint)क्षमता फ़ील्ड्स (process.capabilities.X):
effective - प्रभावी क्षमताएँ बिटमास्क (uint)permitted - अनुमत क्षमताएँ बिटमास्क (uint)inheritable - वंशानुगत क्षमताएँ बिटमास्क (uint)नेमस्पेस फ़ील्ड्स (process.namespaces.X):
net - नेटवर्क नेमस्पेस inode (int)pid - PID नेमस्पेस inode (int)mnt - माउंट नेमस्पेस inode (int)uts - UTS नेमस्पेस inode (int)ipc - IPC नेमस्पेस inode (int)cgroup - Cgroup नेमस्पेस inode (int)कंटेनर फ़ील्ड्स (container.X):
id - कंटेनर ID (स्ट्रिंग)name - कंटेनर नाम (स्ट्रिंग)image - कंटेनर इमेज (स्ट्रिंग)runtime - कंटेनर रनटाइम (स्ट्रिंग)labels - कंटेनर लेबल (मैप)फ़ाइल/सॉकेट फ़ील्ड्स (file.X या socket.X):
path - फ़ाइल पथ (स्ट्रिंग)fd - फ़ाइल डिस्क्रिप्टर नंबर (int)srcPort - स्रोत पोर्ट (int)dstPort - गंतव्य पोर्ट (int)type - सॉकेट प्रकार (tcp, udp)state - सॉकेट स्थिति (फ़िल्टरिंग के लिए, listen, established जैसे स्थिरांक का उपयोग करें)family - पता परिवार (unix, inet, inet6)unixPath - Unix सॉकेट पथ (स्ट्रिंग)fdType - FD प्रकार (file_type, socket_type)अभिव्यक्तियों में बिना उद्धरण के इनका उपयोग करें:
docker, containerd, crio, podmantcp, udpunix, inet, inet6established, listen, syn_sent, syn_recv, fin_wait1, fin_wait2, time_wait, close, close_wait, last_ack, closingfile_type, socket_type