Skip to content

Commit 3b4e403

Browse files
committed
Public launch
0 parents  commit 3b4e403

File tree

2 files changed

+324
-0
lines changed

2 files changed

+324
-0
lines changed

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<p align="center"><img src="https://gnos.in/img/shot/common/gnos-sockets_0.png"></img></p>
2+
3+
# GNOS Sockets
4+
5+
List IP sockets
6+
7+
- auto-sudo
8+
- sane CLI args & defaults
9+
- meaningful color scheme
10+
- searchable sorted output
11+
- shortened addresses (0.0.0.0 -> 0, 127.0.0.1 -> 1)
12+
13+
## Usage
14+
15+
```
16+
Usage: sss [ options ] [ PATTERN ]
17+
18+
-4 Display only IPv4 sockets
19+
-6 Display only IPv6 sockets
20+
-t Display only TCP sockets
21+
-u Display only UDP sockets
22+
-l Display only listening sockets
23+
-L Display only non-listening sockets
24+
-N Resolve numerics
25+
PATTERN Plain-text match
26+
```
27+
28+
## Install
29+
30+
Just copy somewhere in your `$PATH`.
31+
32+
Depends: `ss` `sed` `awk` `sort` `column` `sudo`.

sss

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
#!/bin/bash
2+
# NAME: GNOS sockets
3+
# DESC: Handy ss wrapper
4+
# FEAT: Colors support
5+
# DEPS: ss sed awk sort column sudo
6+
# LICE: WTFPL
7+
8+
9+
10+
########
11+
# FUNC #
12+
########
13+
14+
Usage () # $1:RET
15+
{
16+
cat <<EOF
17+
Usage: $( basename "$( readlink -f "$BASH_SOURCE" )" ) [ options ] [ PATTERN ]
18+
19+
-4 Display only IPv4 sockets
20+
-6 Display only IPv6 sockets
21+
-t Display only TCP sockets
22+
-u Display only UDP sockets
23+
-l Display only listening sockets
24+
-L Display only non-listening sockets
25+
-N Resolve numerics
26+
PATTERN Plain-text match
27+
EOF
28+
exit $1
29+
}
30+
31+
Fix ()
32+
{
33+
sed -E -e 's/^([a-z0-9]+)([A-Z])/\1 \2/' \
34+
-e 's/^([A-Z-]+)([0-9])/\1 \2/'
35+
}
36+
37+
Render () # $1:COLORS $2:PROTO_SUFFIX $3:PATTERN $4:LISTEN $5:NUMERIC
38+
{
39+
awk -v colors=$1 -v suffix=$2 -v pattern="$3" -v listen=$4 -v numeric=$5 -v force=$6 \
40+
-v username=${SUDO_USER:-$USER} -v hostname=$HOSTNAME '
41+
42+
BEGIN {
43+
unknown=":"
44+
45+
# Colors
46+
creset="\033[0m"
47+
cbold="\033[1m"
48+
cred="\033[31m"
49+
cgreen="\033[32m"
50+
cyellow="\033[33m"
51+
cblue="\033[34m"
52+
53+
# Usernames by pid
54+
cmd="ps --no-headers -eo pid,user"
55+
while (cmd | getline v)
56+
{
57+
gsub("^ +" , "", v)
58+
i=index(v, " ")
59+
users[substr(v, 1, i-1)+0]=substr(v, i+1)
60+
}
61+
close(cmd)
62+
63+
# Local ips
64+
cmd="ip a"
65+
while (cmd | getline )
66+
{
67+
if ($1=="inet" || $1=="inet6") locals[ substr($2, 1, index($2, "/")-1) ] = 1
68+
}
69+
close(cmd)
70+
}
71+
72+
{
73+
# Init
74+
nolport=0
75+
76+
# Mapping
77+
if (length(force))
78+
{
79+
proto=force
80+
state=$1
81+
local=$4
82+
remote=$5
83+
user=$6
84+
}
85+
else
86+
{
87+
proto=$1
88+
state=$2
89+
local=$5
90+
remote=$6
91+
user=$7
92+
}
93+
94+
# PROTOCOL
95+
if (proto=="tcp" || proto=="udp") proto=proto suffix
96+
else nolport=1
97+
98+
if (colors)
99+
{
100+
protov=""
101+
if (substr(proto, length(proto))==6)
102+
{
103+
proto=substr(proto, 1, length(proto)-1)
104+
protov=6
105+
}
106+
proto=ColorProto(proto) cred protov creset
107+
}
108+
109+
# LOCAL
110+
laddr=FormatIp(local)
111+
if (colors) laddr=ColorIp(laddr)
112+
lport=local
113+
gsub("^.*:" , "", lport)
114+
if (nolport) lport=""
115+
116+
# REMOTE
117+
if (listen!=1 && force!="udp")
118+
{
119+
raddr=FormatIp(remote)
120+
if (colors) raddr=ColorIp(raddr)
121+
rport=remote
122+
gsub("^.*:" , "", rport)
123+
}
124+
125+
# PROCESS, PID, UID
126+
name=unknown
127+
pid=unknown
128+
uid=unknown
129+
if (substr(user, 1, 6)=="users:")
130+
{
131+
name=substr(user, 10, index(user, "\",")-10)
132+
133+
i=index(user, "=")
134+
pid=substr(user, i+1)
135+
i=index(pid, ",")
136+
pid=substr(pid, 1, i-1)
137+
138+
if (users[pid]) uid=users[pid]
139+
}
140+
if (colors) uid=ColorUser(uid)
141+
142+
# STATE
143+
if (state=="LISTEN" || state=="UNCONN")
144+
{
145+
raddr=""
146+
rport=""
147+
}
148+
if (colors) state=ColorState(state)
149+
150+
# Main
151+
if (listen==1 || force=="udp" ) line=uid " " name " " pid " " proto " " laddr ":" lport " " state
152+
else line=uid " " name " " pid " " proto " " laddr ":" lport " " raddr ":" rport " " state
153+
154+
if (length(pattern))
155+
{
156+
# Filter
157+
raw=" " line
158+
gsub("\033\[[0-9]+m" , "", raw)
159+
# print raw
160+
if (index(raw, pattern)) print line
161+
}
162+
else print line
163+
}
164+
function FormatIp(ip)
165+
{
166+
gsub("(:[^:]*|%.*)$" , "", ip)
167+
if (substr(ip, 1, 1)=="[") ip=substr(ip, 2, length(ip)-2)
168+
if (substr(ip, 1, 7)=="::ffff:") ip=substr(ip, 8)
169+
if (ip=="*" || ip=="0.0.0.0" || ip=="::") ip=0
170+
if (substr(ip, 1, 4)=="127." || ip=="::1" || ip=="localhost") ip=1
171+
return ip
172+
}
173+
function ColorIp(ip)
174+
{
175+
if (ip==0) return cred ip creset
176+
else if (ip==1 || ip=="localhost" || substr(ip, 1, 4)=="127." ) return cgreen ip creset
177+
else if (locals[ip]==1 || ip==hostname) return cblue ip creset
178+
else return cyellow ip creset
179+
}
180+
function ColorProto(p)
181+
{
182+
if (p=="tcp") return cgreen p creset
183+
else if (p=="udp") return cblue p creset
184+
else return cyellow p creset
185+
}
186+
function ColorUser(u)
187+
{
188+
if (u=="root") return cred u creset
189+
else if (u==username) return cgreen u creset
190+
else if (u==unknown) return u
191+
else return cyellow u creset
192+
}
193+
function ColorState(s)
194+
{
195+
if (s=="LISTEN") return cred s creset
196+
else if (s=="ESTAB") return cgreen s creset
197+
else if (s=="UNCONN") return cblue s creset
198+
else return cyellow s creset
199+
}
200+
'
201+
}
202+
203+
204+
########
205+
# INIT #
206+
########
207+
208+
# DEFS
209+
args="$@"
210+
opts="--no-header --extended --processes"
211+
ipv=0
212+
tcp=0
213+
listen=0
214+
numeric=1
215+
216+
# Colors
217+
[[ -t 1 && "$(tput colors)" -ge 8 ]] && colors=$(tput colors)
218+
cyellow='\033[33m'
219+
creset='\033[0m'
220+
cbold='\033[1m'
221+
222+
223+
# ARGS
224+
while getopts hNlL46tu opt "$@" &>/dev/null ; do
225+
case "$opt" in
226+
227+
4) [[ $ipv -eq 6 ]] && ipv=0 || ipv=4 ;;
228+
6) [[ $ipv -eq 4 ]] && ipv=0 || ipv=6 ;;
229+
230+
t) [[ $tcp -eq 2 ]] && tcp=3 || tcp=1 ;;
231+
u) [[ $tcp -eq 1 ]] && tcp=3 || tcp=2 ;;
232+
233+
l) [[ $listen -eq 2 ]] && listen=0 || listen=1 ;;
234+
L) [[ $listen -eq 1 ]] && listen=0 || listen=2 ;;
235+
236+
N) numeric=0 ;;
237+
238+
h) Usage 0 ;;
239+
[?]) Usage 1 ;;
240+
esac
241+
done
242+
shift "$((OPTIND-1))"
243+
[[ $# -gt 1 ]] && Usage 1
244+
pattern=$1
245+
shift
246+
247+
# USER
248+
if [[ $( id -u ) -ne 0 ]] ; then
249+
sudo "$( readlink -f "$BASH_SOURCE" )" $args && exit
250+
[[ -n $colors ]] && echo -en $cyellow >&2
251+
echo "WARNING: Running unprivileged" >&2
252+
[[ -n $colors ]] && echo -en $creset >&2
253+
fi
254+
255+
# OPTS
256+
[[ $numeric -eq 1 ]] && opts="$opts --numeric" || opts="$opts --resolve"
257+
case $listen in
258+
0) opts="$opts --all" ;;
259+
1) opts="$opts --listen" ;;
260+
esac
261+
case $tcp in
262+
0) [[ $listen -eq 2 ]] \
263+
&& opts="$opts --tcp --udp" \
264+
|| opts="$opts --tcp --udp --raw" ;;
265+
3) opts="$opts --tcp --udp" ;;
266+
1) opts="$opts --tcp" ; force=tcp ;;
267+
2) opts="$opts --udp" ; force=udp ;;
268+
esac
269+
270+
271+
########
272+
# MAIN #
273+
########
274+
275+
{
276+
# Header
277+
[[ -n $colors ]] && echo -en $cbold
278+
if [[ $listen -eq 1 || $force == "udp" ]] ; then
279+
echo -n USER PROCESS PID PROTO LOCAL STATE
280+
else
281+
echo -n USER PROCESS PID PROTO LOCAL REMOTE STATE
282+
fi
283+
[[ -n $colors ]] && echo -en $creset
284+
echo
285+
286+
# Data
287+
{
288+
[[ $ipv -eq 4 || $ipv -eq 0 ]] && ss $opts --ipv4 | Fix | Render "$colors" "" "$pattern" "$listen" "$numeric" "$force"
289+
[[ $ipv -eq 6 || $ipv -eq 0 ]] && ss $opts --ipv6 | Fix | Render "$colors" 6 "$pattern" "$listen" "$numeric" "$force"
290+
} | sort -n
291+
292+
} | column -t

0 commit comments

Comments
 (0)