To avoid having to worry with quotes, you can use a here document:
shell_code=$(cat << 'EOF'
journalctl |
awk '
/UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
}'
EOF
)
watch "$shell_code"
(or watch sh -c "$shell_code"
if your watch
implementation does not already start a shell to interpret a command line but runs the command itself, though those watch
implementations are getting rare these days¹).
Some other notes:
awk
can do most of what grep
can do, so you rarely need to pipe them together.
.
is a regular expression operator that matches any single character. grep 192.168.0.2
would match in 192.168.012
. You can use [.]
or \.
to escape it or -F
in grep
or index()
in awk
to do substring searches instead of regex matching.
If you don't add that extra space in the search string, you'd also find DST=192.168.0.2
in DST=192.168.0.234
for instance. Using grep -Fw DST=192.168.0.2
would address both issues.
I would avoid double quotes to enclose shell code, as it would be all too easy to forget to escape $
s or `
s and introduce command injection vulnerabilities (with the contents of variables being potentially interpreted as shell code). Single quotes are safer as you're guaranteed that no character is special within them. As that includes '
s themselves (in Bourne-like shells at least²), that meant you can't have '
s within '...'
, but you can always enter them as 'foo'\''bar'
, which is 'foo'
concatenated with \'
('
quoted with a backslash) concatenated with 'bar'
. So here:
watch 'journalctl |
awk '\''
/UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
}'\'
journalctl
has a -f
/--follow
mode where new log entries are displayed as they arrive. You may want to use that rather than searching the full logs over and over again.
¹ the watch
implementation from procps-ng
runs sh
to interpret the code in the concatenation of its arguments with spaces, though can run commands directly with the -x
/ --exec
option allowing you to more easily have code interpreted by another language interpreter like watch -x zsh -c 'zsh code'
or watch -x perl -e 'perl code'
.
² Though for completeness zsh (Bourne-like; though with features from rc and csh as well) can do 'foo''bar'
to have a single quote inside single quoted strings à la rc
if you enable the rcquotes
option.