함께 프로젝트를 만들어요!
ps
와 같은 Linux 도구 , top
&netstat
훌륭합니다.
시스템 상태에 대한 많은 정보를 제공합니다.
- 하지만 어떻게 작동합니까?
- 모든 정보는 어디에서 얻나요?
- 이를 사용하여 자체 도구를 구축하려면 어떻게 해야 하나요?
이 게시물에서는 세 가지 인기 있는 Linux 도구를 함께 다시 만들 것입니다.
2x1 식사를 하고 Ruby 트릭을 배우고 동시에 유용한 Linux 지식을 얻을 수 있습니다! 🙂
상태 정보 찾기
이제 이 모든 도구가 정보를 찾는 위치에 대한 질문에 답해 보겠습니다.
답은 proc 파일 시스템에 있습니다!
/proc
내부를 보면 디렉토리는 컴퓨터의 다른 디렉토리와 마찬가지로 많은 디렉토리 및 파일처럼 보입니다.
이것은 실제 파일이 아니며 Linux 커널이 사용자에게 데이터를 노출하는 방법일 뿐입니다.
일반 파일처럼 취급할 수 있어 특별한 도구 없이도 읽을 수 있어 매우 편리합니다.
Linux 세계에서는 많은 것들이 이와 같이 작동합니다.
다른 예제를 보고 싶다면 /dev
를 살펴보세요. 디렉토리.
이제 우리가 무엇을 다루고 있는지 이해했으므로 /proc
의 내용을 살펴보겠습니다. 디렉토리...
110104105111101511469114741155211655
이것은 작은 샘플이지만 패턴을 빠르게 알아차릴 수 있습니다.
그 숫자가 모두 무엇입니까?
이것이 PID(프로세스 ID)라는 것이 밝혀졌습니다.
모든 항목에는 특정 프로세스에 대한 정보가 포함되어 있습니다.
ps
를 실행하면 모든 프로세스에 PID가 어떻게 연결되어 있는지 확인할 수 있습니다.
PID TTY 시간 CMD15952 pts/5 00:00:00 ps22698 pts/5 00:00:01 bash
이것으로부터 우리는 ps가 하는 것이 /proc
를 반복한다는 것을 추론할 수 있습니다. 디렉토리 및 찾은 정보를 인쇄합니다.
번호가 매겨진 디렉토리 중 하나에 무엇이 들어 있는지 살펴보겠습니다.
attrautogroupauxvcgroupclear_refscmdlinecommcpusetcwdenvironexefd
공간을 절약하기 위한 샘플일 뿐이지만 전체 목록을 살펴보시기 바랍니다.
흥미로운 항목이 있습니다. :
항목 | 설명 |
---|---|
통신 | 프로그램 이름 |
cmdline | 이 프로세스를 시작하는 데 사용되는 명령 |
환경 | 이 프로세스가 시작된 환경 변수 |
상태 | 프로세스 상태(실행 중, 절전 모드...) 및 메모리 사용량 |
fd | 파일 설명자를 포함하는 디렉토리(열린 파일, 소켓…) |
이제 우리는 이것을 알았으므로 몇 가지 도구를 작성할 수 있어야 합니다!
실행 중인 프로그램을 나열하는 방법
/proc
아래의 모든 디렉토리 목록을 가져오는 것으로 시작하겠습니다. .
Dir
를 사용하여 이 작업을 수행할 수 있습니다. 수업.
예 :
Dir.glob("/proc/[0-9]*")
숫자 범위를 사용한 방법에 주목하세요. 그 이유는 /proc
아래에 다른 파일이 있기 때문입니다. 지금은 신경 쓰지 않고 번호가 매겨진 디렉토리만 원합니다.
이제 이 목록을 반복하고 PID가 있는 열과 프로그램 이름이 있는 열 두 개를 인쇄할 수 있습니다.
예 :
pids =Dir.glob("/proc/[0-9]*")puts "PID\tCMD"puts "-" * 15pids.each do |pid| cmd =File.read(pid + "/comm") pid =pid.scan(/\d+/).first "#{pid}\t#{cmd}"end
이것이 출력입니다 :
PID CMD---------------1 systemd2 kthreadd3 ksoftirqd/05 kworker/07 마이그레이션/08 rcu_preempt9 rcu_bh10 rcu_sched
안녕하세요, 방금 ps
를 만든 것 같습니다. ! 예, 원본의 모든 멋진 옵션을 지원하지는 않지만 우리가 뭔가를 만들었습니다.
누가 듣고 있습니까?
netstat
를 복제해 봅시다. 이제 출력은 다음과 같습니다(-ant
사용). 플래그로).
활성 인터넷 연결(서버 및 설정됨)Proto Recv-Q Send-Q 로컬 주소 외부 주소 상태 tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN tcp 0 0 192.168.1.82:39530 9122.15. 설립
이 정보는 어디에서 찾을 수 있습니까? "/proc
내부 " 네가 옳아! 보다 구체적으로 /proc/net/tcp
에서 찾을 수 있습니다. .
하지만 약간의 문제가 있습니다. 이것은 netstat
처럼 보이지 않습니다. 출력!
0 :0100007F :1538 00000000 :0000 0A 00000000 :00000000 00 :0000000000000000000010101010161 :2E58A8C0 :9A6A 9FBB0EB9 :0016 01 00000000 :00000000 00 :000000000000000000000000 0000000000000000000000000 000이것이 의미하는 바는 정규 표현식으로 일부 구문 분석을 수행해야 한다는 것입니다. 지금은 로컬 주소와 상태에 대해서만 신경쓰자.
여기에 내가 생각해낸 정규식이 있습니다. :
LINE_REGEX =/\s+\d+:(?\w+):(? \w+) \w+:\w+ (? \w+)/ 이것은 10진수로 변환해야 하는 몇 가지 16진수 값을 제공합니다. 이 작업을 수행할 클래스를 만들어 보겠습니다.
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 # 16진수를 일반으로 변환 IP 표기법 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 # 이것에 대해 너무 걱정하지 마십시오. 그것은 이진 수학입니다. def decimal_to_ip(십진수) ip =[] ip <<(십진수>> 24 &0xFF) ip <<(십진수>> 16 &0xFF) ip <<(십진수>> 8 &0xFF) ip <<(십진수 &0xFF) ip.join(".") 끝남은 것은 결과를 예쁜 표 형식으로 인쇄하는 것뿐입니다.
'table_print'tp 연결 필요예시 출력 :
상태 | LOCAL_PORT | LOCAL_ADDR ------------|------------|----------------듣기 | 5432 | 127.0.0.1 설립 | 39530 | 192.168.88.46예, 이 보석은 훌륭합니다!
방금 찾았고
ljust
로 더듬거리지 않아도 될 것 같습니다. /rjust
다시 🙂내 포트 사용을 중지하십시오!
이 메시지를 본 적이 있습니까?
이미 사용 중인 주소 - "localhost" 포트 5000에 대한 bind(2)음...
어떤 프로그램이 그 포트를 사용하고 있는지 궁금합니다.
알아보자 :
fuser -n tcp -v 5000PORT 사용자 PID 액세스 CMD5000/tcp rubyguides 30893 F.... nc아, 범인이 있습니다!
이제 이 프로그램이 실행되는 것을 원하지 않으면 중지할 수 있습니다. 그러면 포트가 해제됩니다. "퓨저" 프로그램은 누가 이 포트를 사용하고 있는지 어떻게 알아냈습니까?
짐작하셨군요!
/proc
다시 파일 시스템.사실, 그것은 우리가 이미 다룬 두 가지를 결합합니다:프로세스 목록을 살펴보고
/proc/net/tcp
에서 활성 연결 읽기 .한 단계만 더하면 됩니다. :
열린 포트 정보를 PID와 일치시키는 방법을 찾으십시오.
<블록 인용>
/proc/net/tcp
에서 얻을 수 있는 TCP 데이터를 보면 , PID가 없습니다. 하지만 inode 번호를 사용할 수 있습니다."inode는 파일 시스템 개체를 나타내는 데 사용되는 데이터 구조입니다." – 위키피디아
inode를 사용하여 일치하는 프로세스를 찾는 방법은 무엇입니까?
fd
아래를 보면 우리가 알고 있는 프로세스의 디렉토리에 열린 포트가 있는 경우 다음과 같은 행을 찾을 수 있습니다./proc/3295/fd/5 -> 소켓:[12345]대괄호 사이의 숫자는 inode 번호입니다. 이제 모든 파일을 반복하면 일치하는 프로세스를 찾을 수 있습니다.
여기에 한 가지 방법이 있습니다. :
x =Dir.glob("/proc/[0-9]*/fd/*").find do |fd| 파일.readlink(fd).include? "소켓:[#{소켓_아이노드}]" 구출 nilendpid =x.scan(/\d+/).firstname =File.readlink("/proc/#{pid}/exe")puts "포트 #{hex_port.to_i( 16)} #{name}(#{pid})에서 사용 중"출력 예:
/usr/bin/postgres(474)에서 사용 중인 포트 5432이 코드를 루트 또는 프로세스 소유자로 실행해야 합니다.
그렇지 않으면
/proc
내부의 프로세스 세부 정보를 읽을 수 없습니다. .결론
이 게시물에서는 Linux가 가상
/proc
를 통해 많은 데이터를 노출한다는 것을 배웠습니다. 파일 시스템. 또한/proc
아래의 데이터를 사용하여 ps, netstat 및 fuser와 같은 인기 있는 Linux 도구를 다시 만드는 방법도 배웠습니다. .다음 게시물을 놓치지 않도록 아래 뉴스레터 구독을 잊지 마세요. 🙂