File conkyconf.SUSE of Package conky
713
1
#!/bin/bash
2
#
3
# system
4
#
5
6
VERSION="0.1"
7
USER_CONFIG_FILE="$HOME/.config/conky/conky.conf"
8
DEFAULT_RSS_URL="https://www.novell.com/newsfeeds/rss/patches/security_notifications-daily.xml"
9
SYSTEM_LOG="| journalctl -q | tail -n 5"
10
USERS_LOG="| who"
11
12
ALIGNMENTS="|top_left|top_right|top_middle|bottom_left|bottom_right|bottom_middle|middle_left|middle_middle|middle_right,tl|tr|tm|bl|br|bm|ml|mm|mr|"
13
14
ip=ip
15
iwconfig=/usr/sbin/iwconfig
16
ss=/usr/sbin/ss
17
18
# log
19
function log()
20
{
21
verb=$1
22
msg="$2"
23
24
if [ $verb -le ${config[verbosity]} ]; then
25
echo "$msg" >&2
26
fi
27
}
28
29
# bail out
30
function die()
31
{
32
msg="$1"
33
log 0 "conkyconf: $msg"
34
log 2 "$0 unsuccessfully finished"
35
exit 1
36
}
37
38
# writing string to file
39
function sys_write_file()
40
{
41
file=$1
42
content=$2
43
44
dir=$(dirname $file)
45
if [ ! -d "$dir" ]; then
46
log 1 "creating $dir"
47
mkdir -p $dir || die "could not create $dir"
48
fi
49
50
log 1 "writing $file"
51
52
echo "$content" > "$file" || die "could not write $file"
53
return
54
}
55
56
# list of all network interfaces
57
function sys_all_network_interfaces()
58
{
59
interfaces=$($ip -br link show | sed 's:\s\+.*::' | grep -v 'tun\|lo' | tr '\n' ' ')
60
log 1 "detected interfaces: $interfaces"
61
echo $interfaces
62
}
63
64
# default interface
65
function sys_default_network_interface()
66
{
67
interface=$($ip route | grep default | sed 's:.*dev \(\S\+\) .*:\1:')
68
log 1 "detected default interface: $interface"
69
echo $interface
70
}
71
72
# wireless or wired network iterface?
73
function sys_network_interface_type()
74
{
75
interface=$1
76
type=$($iwconfig $1 2>&1 | grep -q 'no wireless' && echo "wired" || echo "wireless")
77
log 1 "network interface $interface is $type"
78
echo $type
79
}
80
81
# attached sdX drives
82
function sys_drives()
83
{
84
drives=$(find /dev -maxdepth 1 -type b -name "sd[a-z]" -exec basename "{}" ";" | sort)
85
log 1 "detected drives: $drives"
86
echo $drives
87
}
88
89
# processors
90
function sys_processors()
91
{
92
CPUS=$(getconf _NPROCESSORS_ONLN)
93
CPUS=${CPUS:=1}
94
cpus=$(seq 1 $CPUS | tr '\n' ' ')
95
log 1 "assuming numbers of CPUs: $cpus"
96
echo $cpus
97
}
98
99
# opened ports
100
function sys_opened_ports()
101
{
102
ports=$($ss -nlt | awk '{print $4}' | grep ':::\|\*:' | sed 's/:::\|\*://' | sort -u)
103
log 1 "opened ports: $ports"
104
echo $ports
105
}
106
107
#
108
# global config
109
#
110
111
function conky_config()
112
{
113
cat << EOS
114
conky.config = {
115
background = true,
116
update_interval = 1.5,
117
cpu_avg_samples = 2,
118
net_avg_samples = 2,
119
out_to_console = false,
120
override_utf8_locale = true,
121
double_buffer = true,
122
no_buffers = true,
123
text_buffer_size = 32768,
124
imlib_cache_size = 0,
125
own_window = true,
126
own_window_type = 'desktop',
127
own_window_argb_visual = true,
128
own_window_argb_value = 120,
129
own_window_hints = 'undecorated,below,sticky,skip_taskbar,skip_pager',
130
border_inner_margin = 20,
131
border_outer_margin = 0,
132
alignment = '${config[alignment]}',
133
gap_x = ${config[gap_x]},
134
gap_y = ${config[gap_y]},
135
draw_shades = true,
136
draw_outline = false,
137
draw_borders = false,
138
draw_graph_borders = false,
139
use_xft = true,
140
font = 'monospace:size=9',
141
xftalpha = 0.8,
142
uppercase = false,
143
default_color = '#FFFFFF',
144
own_window_colour = '#000000',
145
maximum_width = 375
146
};
147
148
EOS
149
}
150
151
#
152
# contents of the window
153
#
154
155
# horizontal rule
156
function text_hr()
157
{
158
echo " \${goto 20}\${hr}"
159
}
160
161
# hostname, kernel, date and uptime
162
function text_preamble()
163
{
164
cat << EOS
165
\${goto 20}\${color #DD3A21}\${font monospace:bold:size=20}\${nodename}\${font}\${color}\${goto 250}\${font FontAwesome}\${font}\${voffset -2} \${time %d/%m/%y}
166
\${goto 20}\${color #DD3A21}\${kernel}\${color}\${goto 250}\${font FontAwesome}\${font}\${voffset -2} \${time %H:%M}
167
\${goto 250}\${font FontAwesome}\${font}\${voffset -2} \${uptime}
168
EOS
169
}
170
171
# show one network interface info
172
function text_network_interface
173
{
174
if_name=$1
175
case $(sys_network_interface_type $if_name) in
176
"wired") icon= text="" ;;
177
"wireless") icon=; text="\${exec eval \$(/usr/sbin/iwconfig $if_name | grep 'Link Quality' | sed 's:.*Quality=\([0-9]\+\)/\([0-9]\+\).*:echo \$((\1*100/\2))%:')}" ;;
178
esac
179
cat << EOS
180
\${goto 20}\${font FontAwesome}$icon\${font}\${voffset -2} $if_name \${addrs $if_name} $text
181
\${goto 20}\${upspeedgraph $if_name 30,178 06E9F8 2104FA}\${goto 202}\${downspeedgraph $if_name 30,175 FFFF00 DD3A21}
182
\${goto 20}\${font FontAwesome}\${font}\${voffset -2} \${upspeed $if_name}\${font FontAwesome}\${goto 202}\${font}\${voffset -2} \${downspeed $if_name}
183
EOS
184
}
185
186
# memory info
187
function text_memory
188
{
189
cat << EOS
190
\${goto 20}\${font FontAwesome}\${font}\${voffset -2} \${mem}/\${memmax} (\${memperc}%) | Swap: \${swapperc}%
191
\${goto 20}\${memgraph 30,355 AAF5D0 00B35B}
192
EOS
193
}
194
195
# attached drive info
196
function text_drive
197
{
198
name=$1
199
200
201
cat << EOS
202
\${goto 20}\${font FontAwesome}\${font}\${voffset -2} $name
203
\${goto 20}\${diskiograph_read $name 30,178 06E9F8 2104FA}\${goto 202}\${diskiograph_write $name 30,175 FFFF00 DD3A21}
204
\${goto 20}\${font FontAwesome}\${goto 20}\${font}\${voffset -2} \${diskio_read $name}\${font FontAwesome}\${voffset -2}\${goto 202}\${font} \${diskio_write $name}
205
EOS
206
}
207
208
# processor info
209
function text_processor
210
{
211
name=$1
212
cat << EOS
213
\${goto 20}CPU$name: \${goto 90}\${cpu cpu$name}%\${goto 140}\${cpubar cpu$name 7,70}\${goto 230}\${freq_g $name} GHz
214
EOS
215
}
216
217
# process table
218
function text_processes
219
{
220
echo " \${color #FFFF00}\${goto 20}Name \${goto 200}Pid\${goto 255}Cpu%\${goto 310}Mem%\${color}"
221
for i in $(seq 1 5); do
222
echo " \${goto 20}\${top name $i} \${goto 180}\${top pid $i}\${goto 235}\${top cpu $i}\${goto 290}\${top mem $i}"
223
done
224
}
225
226
# rss feed
227
function text_rss
228
{
229
url=$1
230
cat << EOS
231
\${goto 20}\${font FontAwesome}\${font}\${voffset -2} \${color #FFFF00}\${scroll 50 2 \${rss $url 10 item_titles 5}}\${color}
232
EOS
233
}
234
235
# port monitor
236
function text_portmon()
237
{
238
port_range=$1
239
240
echo -n " \${goto 20}"
241
if [[ $port_range =~ "-" ]]; then
242
echo -n "\${font FontAwesome}\${font}\${voffset -2} Port range $port_range"
243
port_range="$(tr '-' ' ')"
244
else
245
echo -n "\${font FontAwesome}\${font}\${voffset -2} Port $port_range"
246
port_range="$port_range $port_range"
247
echo -n ", service \${tcp_portmon $port_range lservice 0}"
248
fi
249
echo " (\${tcp_portmon $port_range count} connections)"
250
251
for i in $(seq 0 4); do
252
echo -n " \${goto 20}\${font monospace:size=8}"
253
echo -n "\${if_match \"\${tcp_portmon $port_range rip $i}\" != \"\"}"
254
echo -n "\${tcp_portmon $port_range rip $i}:"
255
echo -n "\${tcp_portmon $port_range rport $i} "
256
echo -n "\${tcp_portmon $port_range rhost $i} "
257
echo -n "\${if_match \"\${tcp_portmon $port_range rport $i}\" != \"\${tcp_portmon $port_range rservice $i}\"}"
258
echo -n "\${tcp_portmon $port_range rservice $i} "
259
echo -n "\${endif}"
260
echo -n "\${else}"
261
echo -n "-"
262
echo -n "\${endif}"
263
echo "\${font}"
264
done
265
266
}
267
268
# text when no port are defined
269
function text_portmon_no_ports()
270
{
271
echo " \${goto 20}Port monitor: no ports defined."
272
}
273
274
# logfile (including program outputs)
275
function text_log
276
{
277
logfile=$1
278
font_size=${2:-8}
279
280
echo -n " \${goto 20}\${font monospace:size=$font_size}"
281
if [[ "$logfile" =~ ^[[:space:]]*\| ]]; then
282
logfile=$(echo $logfile | sed 's:^\s*|\s*::')
283
log 1 "will read log from [$logfile] program"
284
echo -n \${texeci 10 $logfile}
285
else
286
log 1 "will read log from [$logfile] file"
287
echo -n \${tail $logfile 5}
288
fi
289
echo \${font}
290
}
291
292
function conky_text()
293
{
294
echo
295
echo "conky.text = [["
296
content_index=0
297
while [ -n "${contents[$content_index]}" ]; do
298
case "${contents[$content_index]}" in
299
preamble)
300
text_preamble
301
;;
302
hrule)
303
text_hr
304
;;
305
networkif*)
306
for nif in ${contents_arg[$content_index]}; do
307
text_network_interface $nif
308
done
309
;;
310
memory)
311
text_memory
312
;;
313
drives)
314
for d in ${contents_arg[$content_index]}; do
315
text_drive $d
316
done
317
;;
318
processors)
319
for p in ${contents_arg[$content_index]}; do
320
text_processor $p
321
done
322
;;
323
processes)
324
text_processes
325
;;
326
rss)
327
text_rss ${contents_arg[$content_index]}
328
;;
329
portmon)
330
if [ -n "${contents_arg[$content_index]}" ]; then
331
for range in ${contents_arg[$content_index]}; do
332
text_portmon $range
333
done
334
else
335
text_portmon_no_ports
336
fi
337
;;
338
log*)
339
fontsize=$(echo ${contents[$content_index]} | sed 's/.*://')
340
text_log "${contents_arg[$content_index]}" $fontsize
341
esac
342
content_index=$((content_index+1))
343
done
344
echo "]];"
345
}
346
347
# string is integer
348
function arg_is_numeric()
349
{
350
[[ "$1" =~ ^[0-9]+$ ]] && return 0 || return 1
351
}
352
353
# string is option
354
function arg_is_option()
355
{
356
arg=$1
357
[ ${arg:0:1} == '-' ] && return 0 || return 1
358
}
359
360
function arg_is_alignment()
361
{
362
[[ "$ALIGNMENTS" =~ "|$1|" ]] && return 0 || return 1
363
}
364
365
# end of argument list
366
function arg_is_end()
367
{
368
[ -z "$1" ] && return 0 || return 1
369
}
370
371
# split list argument, delimiters: [:,;]
372
function arg_split_list()
373
{
374
echo $1 | tr ':,;' ' '
375
}
376
377
# help on this script usage
378
function conkyconf_usage()
379
{
380
cat << EOS
381
$(echo ${0##*/} | tr [a-z] [A-Z]), version $VERSION
382
383
conky configuration example generator
384
385
USAGE
386
387
conkyconf --par1 [arg11 [arg12]] --par2 [arg21 [arg22]] ...
388
389
There are object parameters (as --memory, --networkif, --rule) and
390
non-object parameters (as --verbosity, --file). Object parameters
391
will add corresponding objects to conky configuration in that
392
order. Objects can be repeated for different arguments by
393
repeating it on command line.
394
395
More conky instantions can be launched, but then different configuration
396
files has to be used (see -f|--file option).
397
398
Configuration is written to
399
400
$USER_CONFIG_FILE
401
402
which has a precedence before system wide configuration file.
403
404
PARAMETERS
405
406
-h|--help this help
407
-v|--verbosity [verb] debug output of the script, 0 (just errors)
408
1 or 2
409
-f|--file <conffile> write the configuration to this file
410
-g|--geometry [a [x [y]]] geometry of conky window, parameters:
411
* a -- alignment top_left (tl), bottom_middle
412
(bm), middle_left (ml), middle_middle
413
(mm), etc.
414
* x -- gap between window and attached
415
vertical border
416
* y -- gap between window and attached
417
horizontal border
418
419
420
-r|--rule add horizontal rule
421
-p|--preamble host, kernel, time and uptime info
422
-n|--networkif [ifcs] network interface(s) info; arguments:
423
* 'all' -- all interfaces are monitored
424
* <no arg> -- default interface is chosen
425
* <list> -- comma, colon or semicolon
426
separated list of interfaces
427
-m|--memory memory info
428
-d|--drives [drvs] sdaX drives info; arguments:
429
* 'all' -- all drives are monitored
430
* <no arg> -- the same as 'all'
431
* <list> -- comma, colon or semicolon
432
separated list of drives
433
-c|--cpu add all CPUs info
434
-e|--processes show process table
435
-s|--rss [url] add a rss feed; if no url is given,
436
SUSE security rss feed is chosen
437
-t|--portmon [ports] display port monitor; arguments:
438
* <no arg> -- display opened ports
439
* <list> -- comma, colon or semicolon
440
separated list of ports
441
-l|--log [log [fs]] show tail of a log; arguments:
442
log:
443
* | <program> -- show output of the
444
program
445
* <file> -- show last 5 lines of
446
the log
447
* <noarg> -- $SYSTEM_LOG
448
fs: font size of the output
449
450
451
-u|--default choose default profile; objects can be added
452
or prepended
453
454
NOTE
455
456
Everytime some of monitored objects are changed, for example new port is
457
opened, usb stick is plugged in or connection is changed from wireless to
458
wired (and just default interface is monitored), then conkyconf has to be
459
rerun. conky then rereads the configuration automatically.
460
461
EXAMPLES
462
463
conkyconf --default
464
465
Uses built in preset.
466
467
conkyconf --preamble -r --networkif -r --drives -r --cpu
468
469
Shows preamble, default network interface, all attached
470
drives and cpu information, in that order.
471
472
conkyconf --preamble -r --drives sda:sdb -r --networkif em1 \\
473
-r --cpu -r --log '|who' 8 -r --log
474
475
Displays peramble, network drives sda and sdb, interface em1 and
476
cpu information and also output of who command in font size 8
477
and system log in default font size for logs.
478
EOS
479
}
480
481
482
483
declare -A contents
484
declare -A contents_arg
485
declare -A config
486
487
config[verbosity]=0
488
config[file]="$USER_CONFIG_FILE"
489
config[alignment]="bottom_right"
490
config[gap_x]="70"
491
config[gap_y]="70"
492
493
if [ -z "$1" ]; then
494
set -- "--help"
495
fi
496
497
content_index=0
498
while [ -n "$1" ]; do
499
arg_is_option "$1" || die "option starting with '-' or '--' expected ($1)"
500
501
case "$1" in
502
-h|--help)
503
conkyconf_usage
504
exit 0
505
;;
506
-v|--verbosity)
507
shift
508
if ! arg_is_end "$1" && arg_is_numeric "$1"; then
509
config[verbosity]="$1"
510
shift;
511
else
512
config[verbosity]=2
513
fi
514
log 1 "verbosity set to ${config[verbosity]}"
515
;;
516
-p|--preamble)
517
shift
518
log 2 'adding preamble'
519
contents[$content_index]="preamble"
520
content_index=$((content_index+1))
521
;;
522
-r|--hrule)
523
shift
524
log 2 'adding horizontal rule'
525
contents[$content_index]="hrule"
526
content_index=$((content_index+1))
527
;;
528
-n|--networkif)
529
shift
530
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
531
if [ $1 == "all" ]; then
532
devices="$(sys_all_network_interfaces)"
533
else
534
devices="$(arg_split_list $1)"
535
fi
536
shift
537
else
538
devices="$(sys_default_network_interface)"
539
fi
540
log 2 "adding network interface monitor: $devices"
541
contents[$content_index]="networkif"
542
contents_arg[$content_index]="$devices"
543
content_index=$((content_index+1))
544
;;
545
-m|--memory)
546
shift
547
log 2 'adding memory info'
548
contents[$content_index]="memory"
549
content_index=$((content_index+1))
550
;;
551
-d|--drives)
552
shift
553
# -d and -d all the same effect
554
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
555
if [ "$1" == "all" ]; then
556
drives="$(sys_drives)"
557
else
558
drives="$(arg_split_list $1)"
559
fi
560
shift
561
else
562
drives="$(sys_drives)"
563
fi
564
log 2 "adding hard drives: $drives"
565
contents[$content_index]="drives"
566
contents_arg[$content_index]="$drives"
567
content_index=$((content_index+1))
568
;;
569
-c|--cpu)
570
shift
571
processors="$(sys_processors)"
572
log 2 "adding cpu units: $processors"
573
contents[$content_index]="processors"
574
contents_arg[$content_index]="$processors"
575
content_index=$((content_index+1))
576
;;
577
-e|--processes)
578
shift
579
log 2 "adding process table"
580
contents[$content_index]="processes"
581
content_index=$((content_index+1))
582
;;
583
-s|--rss)
584
shift
585
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
586
url="$1"
587
else
588
url="$DEFAULT_RSS_URL"
589
fi
590
log 2 "adding rss feed: $url"
591
contents[$content_index]="rss"
592
contents_arg[$content_index]="$url"
593
content_index=$((content_index+1))
594
;;
595
-t|--portmon)
596
shift
597
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
598
port_ranges="$(arg_split_list $1)"
599
shift
600
else
601
port_ranges="$(sys_opened_ports)"
602
fi
603
log 2 "adding port monitor for port ranges: $port_ranges"
604
contents[$content_index]="portmon"
605
contents_arg[$content_index]="$port_ranges"
606
content_index=$((content_index+1))
607
;;
608
-l|--log)
609
shift
610
if ! arg_is_end "$1" && ! arg_is_option "$1" && ! arg_is_numeric "$1"; then
611
log="$1"
612
shift
613
else
614
log="$SYSTEM_LOG"
615
fi
616
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
617
if arg_is_numeric "$1"; then
618
font_size="$1"
619
shift
620
else
621
die "numeric argument (font size of the log) expected"
622
fi
623
else
624
font_size=6
625
fi
626
log 2 "adding logging: $log"
627
contents[$content_index]="log:$font_size"
628
contents_arg[$content_index]="$log"
629
content_index=$((content_index+1))
630
;;
631
-u|--default)
632
shift
633
contents[0]="preamble"
634
contents[1]="hrule"
635
contents[2]="networkif"
636
contents_arg[2]="$(sys_default_network_interface)"
637
contents[3]="hrule"
638
contents[4]="drives"
639
contents_arg[4]="$(sys_drives)"
640
contents[5]="hrule"
641
contents[6]="processors"
642
contents_arg[6]="$(sys_processors)"
643
contents[7]="hrule"
644
contents[8]="processes"
645
contents[9]="hrule"
646
contents[10]="portmon"
647
contents_arg[10]="$(sys_opened_ports)"
648
contents[11]="hrule"
649
contents[12]="log:8"
650
contents_arg[12]="$USERS_LOG"
651
contents[13]="hrule"
652
contents[14]="log:6"
653
contents_arg[14]="$SYSTEM_LOG"
654
contents[15]="hrule"
655
contents[16]="rss"
656
contents_arg[16]="$DEFAULT_RSS_URL"
657
content_index=17
658
;;
659
-f|--file)
660
shift
661
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
662
config[file]="$1"
663
shift
664
else
665
die "-f|--file requires an argument"
666
fi
667
;;
668
-g|--geometry)
669
shift
670
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
671
if ! arg_is_alignment "$1"; then
672
die "first argument of -g|--geometry has to be one of $ALIGNMENTS"
673
fi
674
config[alignment]="$1"
675
shift
676
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
677
if ! arg_is_numeric "$1"; then
678
die "second argument of -g|--geometry has to be a number"
679
fi
680
config[gap_x]="$1"
681
shift
682
if ! arg_is_end "$1" && ! arg_is_option "$1"; then
683
if ! arg_is_numeric "$1"; then
684
die "third argument of -g|--geometry has to be a number"
685
fi
686
config[gap_y]="$1"
687
shift
688
fi
689
fi
690
else
691
die "-g|--geometry requires an argument"
692
fi
693
;;
694
*)
695
die "unsupported option ($1)"
696
shift
697
;;
698
esac
699
done
700
701
log 2 "arguments parsed"
702
703
log 1 "geometry: ${config[alignment]}, ${config[gap_x]}, ${config[gap_y]}"
704
705
log 2 "creating configuration"
706
conky_configuration="$(conky_config)$(conky_text)"
707
708
log 2 "wrinting configuration"
709
sys_write_file ${config[file]} "$conky_configuration"
710
711
log 2 "$0 successfully finished"
712
713