그래서 미친 듯이 찾아봤지만 아직 만족스러운 해결책을 찾지 못했습니다. 아래와 같이 출력이 있습니다.
kdeconnec 1625 1000 11u IPv6 414426 0t0 UDP *:1716
vivaldi-b 1937 1000 263u IPv4 440390 0t0 UDP 224.0.0.251:5353
electron 9522 1000 23u IPv4 414465 0t0 TCP 192.168.0.17:58692->157.240.194.18:443 (ESTABLISHED)
flask 27084 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
firefox 27094 1000 99u IPv4 425877 0t0 TCP 192.168.0.17:34114->54.191.222.112:443 (ESTABLISHED)
python 36425 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
chromium 110937 1000 130u IPv4 439461 0t0 UDP 224.0.0.251:5353
exec_path_from_process_id
각 값에 다음과 같은 함수를 적용하고 싶습니다 .두번째열을 다음과 같이 삽입하십시오.두번째기둥. 결과는 다음과 같습니다. 정확한 형식(정렬)은 중요하지 않으며 단지 정렬만 하면 됩니다.
kdeconnec /usr/lib/kdeconnectd 1625 1000 11u IPv6 414426 0t0 UDP *:1716
vivaldi-b /opt/vivaldi/vivaldi-bin 1937 1000 263u IPv4 440390 0t0 UDP 224.0.0.251:5353
electron /usr/lib/electron/electron 9522 1000 23u IPv4 414465 0t0 TCP 192.168.0.17:58692->157.240.194.18:443 (ESTABLISHED)
flask /usr/bin/python3.10 27084 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
firefox /usr/lib/firefox/firefox 27094 1000 99u IPv4 425877 0t0 TCP 192.168.0.17:34114->54.191.222.112:443 (ESTABLISHED)
python /usr/bin/python3.10 36425 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
chromium /usr/lib/chromium/chromium 110937 1000 130u IPv4 439461 0t0 UDP 224.0.0.251:5353
kioslave5 /usr/lib/kf5/kioslave5 133514 1000 6u IPv4 499063 0t0 TCP 192.168.0.17:54238->84.208.4.225:443 (ESTABLISHED)
내 현재 코드는 엉망이지만 적어도 작동하게 만들었습니다. 유일한 제한은 bash 3.2 이상에서 실행되어야 한다는 것입니다.
listeners=$(
lsof -Pnl +M -i |
awk -F" " '!_[$1]++' |
tail -n +2
)
function exec_path_from_process_id () {
local pid="${1}"
path=$(readlink -f /proc/"$pid"/exe)
if [ -z "${path}" ]; then
path=$(awk '{print $(NF)}' <<< $(ls -alF /proc/"$pid"/exe))
fi
echo ${path:-null}
}
pids=($(awk '{ print $2 }' <<< "$listeners"))
IFS=$'\n' read -rd '' -a listeners_array <<< "$listeners"
IFS=$'\n' read -rd '' -a paths <<< $(for i in "${pids[@]}"; do exec_path_from_process_id "$i"; done)
for i in "${!pids[@]}"; do
row="${listeners_array[i]}"
row=$(awk -v r="${paths[i]}" '{ print $1 " " r " " $2 " " $3 " " $4 " " $5 " " $6 " " $7 " " $8 " " $9 " " $10}' <<< $row)
printf '%s\n' "${row[@]}"
done | column -t
답변1
어쩌면 다음과 같은 것일 수도 있습니다.
lsof -Pnl +M -i | awk '
# Use: NR > 1 to skip header
NR > 1 && !x[$1]++ {
# realpath -m
# (no path components need exist or be a directory)
cmd = "realpath -m /proc/"$2"/exe"
cmd | getline path
close(cmd)
# We can edit field $2 and print $0
$2 = path" "$2
print $0
}' | column -t
이 줄은 cmd | getline path
명령을 실행 cmd
하고 출력을 변수로 읽습니다 path
. 누군가가 닫지 않으면 명령이 닫히지 않으므로 close(expression)
변수에 넣었습니다.
답변2
필드가 정렬되어 있으면 서식 지정에 신경 쓰지 않고 필요에 맞게 충분히 큰 너비를 선택한 다음 다음을 수행한다고 말씀하셨습니다.
$ while read -r a pid b; do
printf "%-12s%-10s%10s %s\n" "$a" "<$(wc -c <<<"$pid")>" "$pid" "$b"
done < <(lsof -Pnl +M -i)
kdeconnec <5> 1625 1000 11u IPv6 414426 0t0 UDP *:1716
vivaldi-b <5> 1937 1000 263u IPv4 440390 0t0 UDP 224.0.0.251:5353
electron <5> 9522 1000 23u IPv4 414465 0t0 TCP 192.168.0.17:58692->157.240.194.18:443 (ESTABLISHED)
flask <6> 27084 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
firefox <6> 27094 1000 99u IPv4 425877 0t0 TCP 192.168.0.17:34114->54.191.222.112:443 (ESTABLISHED)
python <6> 36425 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
chromium <7> 110937 1000 130u IPv4 439461 0t0 UDP 224.0.0.251:5353
위의 내용은 첫 번째 열에 공백이 없다고 가정합니다.
분명히 <$(wc -c <<<"$pid")>
실행해야 하는 실제 명령으로 변경하고 첫 번째 명령을 %-10s
해당 명령이 출력할 수 있는 최대 너비 문자열로 변경하면 됩니다. 이 너비에 사용할 수 있는 최대값이 없다고 생각되는 경우 알려주시면 2단계 접근 방식이 사용됩니다. 즉, 1단계는 출력을 생성하고 2단계는 출력 형식을 지정합니다. 사용 중인 형식이 만족 스러우면 column -t
다음과 같습니다( 분명히 실제로 사용할 수 없는 file
형식으로 대체).<(lsof -Pnl +M -i)
$ while read -r a pid b; do
printf "%s %s %s %s\n" "$a" "<$(wc -c <<<"$pid")>" "$pid" "$b"
done < file | column -t
kdeconnec <5> 1625 1000 11u IPv6 414426 0t0 UDP *:1716
vivaldi-b <5> 1937 1000 263u IPv4 440390 0t0 UDP 224.0.0.251:5353
electron <5> 9522 1000 23u IPv4 414465 0t0 TCP 192.168.0.17:58692->157.240.194.18:443 (ESTABLISHED)
flask <6> 27084 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
firefox <6> 27094 1000 99u IPv4 425877 0t0 TCP 192.168.0.17:34114->54.191.222.112:443 (ESTABLISHED)
python <6> 36425 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
chromium <7> 110937 1000 130u IPv4 439461 0t0 UDP 224.0.0.251:5353
그러나 pid에서 실행하는 명령의 출력과 같이 줄의 일부에 공백이 포함되어 있으면 실패합니다.
귀하가 요청한 대로 다음은 2단계 방법입니다.
- 위와 같이 공백으로 구분된 필드와 줄바꿈으로 구분된 레코드를 사용하여 텍스트를 출력하는 대신 줄바꿈으로 구분된 필드와 NUL로 구분된 레코드를 사용하여 출력을 생성합니다.
while read -r a pid b; do printf "%s\n%s\n%s\n%s\0" "$a" "<$(wc -c <<<"$pid")>" "$pid" "$b"; done < file
- 개행으로 구분된 필드가 포함된 NUL 구분 레코드를 읽고, 입력을 읽을 때 각 필드의 최대 너비를 계산하고, 출력을 인쇄할 때 각 필드를 해당 너비로 출력하고 필드를 단일 OK로 재그룹화하는 awk 스크립트를 작성합니다.
$ while read -r a pid b; do printf "%s\n%s\n%s\n%s\0" "$a" "<$(wc -c <<<"$pid")>" "$pid" "$b"; done < file |
awk -v RS='\0' -F'\n' '
{ recs[NR]=$0; for (i=1; i<=NF; i++) wids[i]=(length($i)>wids[i] ? length($i) : wids[i]) }
END { for (n=1; n<=NR; n++) { $0=recs[n]; for (i=1;i<=NF;i++) printf "%-*s%s", wids[i], $i, (i<NF ? OFS : ORS) } }
'
kdeconnec <5> 1625 1000 11u IPv6 414426 0t0 UDP *:1716
vivaldi-b <5> 1937 1000 263u IPv4 440390 0t0 UDP 224.0.0.251:5353
electron <5> 9522 1000 23u IPv4 414465 0t0 TCP 192.168.0.17:58692->157.240.194.18:443 (ESTABLISHED)
flask <6> 27084 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
firefox <6> 27094 1000 99u IPv4 425877 0t0 TCP 192.168.0.17:34114->54.191.222.112:443 (ESTABLISHED)
python <6> 36425 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
chromium <7> 110937 1000 130u IPv4 439461 0t0 UDP 224.0.0.251:5353
이를 위해서는 GNU awk와 같이 NUL로 구분된 입력을 읽을 수 있는 awk가 필요합니다. 경로 이름이나 다른 필드에는 개행 문자가 포함될 수 없다고 가정합니다.
위의 모든 작업을 하나의 awk 스크립트에서 실제로 수행하려면 외부 명령을 호출할 때마다 awk가 하위 쉘을 분리해야 하며 이는 속도가 느리고 올바르게 인용해야 함을 의미합니다(참조http://awk.freeshell.org/AllAboutGetline) 그러나 여기서는 입력 필드의 공백을 유지하는 데 관심이 없지만 경로의 줄바꿈이 아닌 공백은 괜찮다고 가정합니다.
$ awk '
{
recs[NR] = $0
for (i=1; i<=NF; i++) {
lgth = length($i)
wids[i] = ( lgth > wids[i] ? lgth : wids[i] )
}
cmd = "wc -c <<<\047" $2 "\047"
paths[NR] = ( (cmd | getline line) > 0 ? line : "N/A" )
close(cmd)
lgth = length(paths[NR])
pathWid = ( lgth > pathWid ? lgth : pathWid )
}
END {
for (n=1; n<=NR; n++) {
$0 = recs[n]
for (i=1; i<=NF; i++) {
if ( i == 2 ) {
printf "%-*s%s", pathWid, paths[n], OFS
}
printf "%-*s%s", wids[i], $i, (i<NF ? OFS : ORS)
}
}
}
' < file
kdeconnec 5 1625 1000 11u IPv6 414426 0t0 UDP *:1716
vivaldi-b 5 1937 1000 263u IPv4 440390 0t0 UDP 224.0.0.251:5353
electron 5 9522 1000 23u IPv4 414465 0t0 TCP 192.168.0.17:58692->157.240.194.18:443 (ESTABLISHED)
flask 6 27084 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
firefox 6 27094 1000 99u IPv4 425877 0t0 TCP 192.168.0.17:34114->54.191.222.112:443 (ESTABLISHED)
python 6 36425 1000 3u IPv4 109532 0t0 TCP 127.0.0.1:3000 (LISTEN)
chromium 7 110937 1000 130u IPv4 439461 0t0 UDP 224.0.0.251:5353