Score:4

Bash - variable assignment in a pipeline

bi flag

I am trying to create a script that monitors for failed login attempts and passes the IP address of those attempts as a variable. But I am having a bit of trouble.

I have the below command which spits out the IP addresses as expected.

tail -10 /var/log/authlog | grep '403 Forbidden' | grep -oE '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | sort | uniq | sort

But I am struggling with getting them to pass as a variable.

tail -10 /var/log/authlog | grep '403 Forbidden' | ip_addr=$(grep -oE '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | sort | uniq | sort) 
echo "The following IPs have failed login '$ip_addr'"

I get this as output.

The following IPs have failed login ''

Any assistance would be much appreciated.

Update:

I still had no luck getting the output to pass as a variable, so I just decided to output it to a file.

tail -10 /var/log/authlog | grep '403 Forbidden' | grep -oE '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | sort | uniq | sort >> iplist.txt
waltinator avatar
it flag
Cut your original command at each pipe, and see if the output is what you expect. E.g. `tail -10 /var/log/authlog`, then `tail -10 /var/log/authlog | grep '403 Forbidden'`, ... .
waltinator avatar
it flag
Be sure to use the `--line-buffered` option on both of your `grep`s. Without it, `grep` won't output anything until it gets a buffer full of matches, or sees EOF.
petep avatar
in flag
grep -i ssh /var/log/auth.log | grep -i accept | tr -s " " | cut -d" " -f11 | sort -u
petep avatar
in flag
type "sudo lastb"
Score:1
jp flag

Your variable assignment using command substitution in the pipeline is actually working, but in a subshell rather than the current running shell ... That's how a pipeline works in Bash (i.e. Each command in a multi-command pipeline, where pipes are created, is executed in its own subshell, which is a separate process) ... Therefor, when the subshell for that part of the pipeline dies, the variable assigned will die with it as well ... Please, compare the following two situations:

$ echo "line1 word1 word2" | var="$(grep -o word1)"; echo "${var:-empty}"
empty
$
$ echo "line1 word1 word2" | (var="$(grep -o word1)"; echo "${var:-empty}")
word1

Fortunately, Bash has a shell option lastpipe which:

If set, and job control is not active, the shell runs the last command of a pipeline not executed in the background in the current shell environment.

Job Control is deactivated by default for non-interactive Bash shells i.e. the kind that your executable script file is run in with e.g. ./scriptfile ... But, you can deactivate it even in interactive Bash shells with set +m ... Please, compare the following two situations:

$ (echo "line1 word1 word2" | var="$(grep -o word1)"; echo "${var:-empty}")
empty
$
$ (shopt -s lastpipe; echo "line1 word1 word2" | var="$(grep -o word1)"; echo "${var:-empty}")
word1

Therefore, you can add shopt -s lastpipe to the top of your script file before the pipe-lined commands to enable that behavior.

mpboden avatar
do flag
I just learned something. Thank you. :) Now is there an advantage (or disadvantage) to using `shopt -s lastpipe` over what I suggested as an answer?
Raffa avatar
jp flag
You're welcome @mpboden ... It's an honor for me :-) ... In your suggested solution, the assignment happens after the pipeline closes while with `lastpipe`, the assignment happens while it's open ... Other than that the end result is basically the same AFAIK.
Score:0
it flag

Once you enable the logging by sudo touch /etc/{w,b}tmp, the sudo lastb command will show an up-to-date list of bad logins.

You could also learn from the fail2ban package. fail2ban(1) a set of server and client programs to limit brute force authentication attempts.. Install it and read the documentationn, and the scripts.

Score:0
do flag

Change your command around so that the variable is at the beginning instead of in the middle. Such as the following:

ip_addr=$(tail -10 /var/log/authlog | grep '403 Forbidden' | grep -oE '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | sort | uniq | sort)
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.