0

I am trying to write a script which extracts data from the file "nohup.out" using tail -f and executing dig command on condition.

#!/bin/bash
nohup proxychains firefox

tail -f nohup.out | xargs if [[ {} == *"denied"* ]] 
    then
        dig -x `cut -d '-' -f 6 {} | cut -d ':' -f 1`&;
    fi

Output of nohup.out is

|S-chain|-<>-10.1.1.16:80-<><>-93.184.220.29:80-<--denied

|S-chain|-<>-10.1.1.16:80-<><>-93.184.220.29:80-<--denied

|S-chain|-<>-10.1.1.16:80-<><>-216.58.209.77:443-<><>-OK

|S-chain|-<>-10.1.1.16:80-<><>-46.28.247.89:443-<><>-OK

With the below command I am able to extract the IP for reverse DNS lookup.

cut -d '-' -f 6 | cut -d ':' -f 1

I am not able to find a way to pass the argument to cut and if command.

Community
  • 1
  • 1
DarKnight
  • 83
  • 10
  • The problem is very similar to the one in [Why can't I use Unix `nohup` with Bash `for` loop?](http://stackoverflow.com/questions/3099092/), and the answer and workaround are substantially the same. You probably also need to use `xargs -I '{}' …` too. – Jonathan Leffler Sep 17 '15 at 05:19
  • nohup is used to run firefox with proxychains here, it has nothing to do with the later script. In later script I am reading the output of nohup.out. – DarKnight Sep 17 '15 at 05:22
  • 1
    I didn't say it did; but the problem in the other question is about how to use a Bash built-in — in that case a `for` loop instead of an `if` statement in this case — with a command that takes another command as an argument (`nohup` in the other question, `xargs` in this question). The fact the your `tail -f` command is reading `nohup.out` is completely tangential. – Jonathan Leffler Sep 17 '15 at 05:25
  • Can you use something with `tail -f nohup.out | cut -d '-' -f 6 {} | cut -d ':' -f 1 | while read ip; do` ? – Walter A Sep 17 '15 at 06:23

2 Answers2

1

What you need is to convert the if statement into an argument to bash. Doing a simplistic transform, assuming that the code in the question has a chance of working, you get:

tail -f nohup.out |
xargs -I '{}' bash -c "if [[ {} == *"denied"* ]]; then dig -x $(cut -d '-' -f 6 {} | cut -d ':' -f 1) & fi"

This is exactly the same basic treatment as was needed for a for loop being executed by nohup — you need a shell to run the built-in command. See Why can't I use Unix nohup with Bash for loop? for an exactly analogous situation.

However, on further reflection, you want to cut the string which is the IP address, not the file with that as a name, so the command needs to echo the string into the cut commands. You also have to tear your hair getting the sub-commands executed correctly; you need a backslash before the $ of $(…), or before each of the back-ticks if you insist on using `…` notation, as well as using backslash-double-quote to protect the angle-brackets in the string.

tail -f nohup.out |
xargs -I '{}' bash -c "if [[ '{}' != *denied* ]]; then echo dig -x \"\$(echo '{}' | cut -d '-' -f 6 | cut -d ':' -f 1)\" & fi"

Now we need to debate the use of the condition and two cut commands (and the general hair loss). You could use:

tail -f nohup.out |
grep -v denied |
xargs -I '{}' bash -c "echo dig -x \$(echo '{}' | cut -d '-' -f 6 | cut -d ':' -f 1) &"

or, more sensibly:

tail -f nohup.out |
awk -F '[-:]' '/denied/ { next } { print "dig -x " $7 " &" }' |
sh -x

or any of a myriad other ways to do it.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • All the above are showing some error ( I have replaced `dig -x` with `echo` to get the required ip); 1. It is printing complete line of `if` command 2. `cut {}` no such file or directory 3. no output. – DarKnight Sep 17 '15 at 06:38
  • I don't know what your problem with the `awk`/`sh` combination is; that worked for me (it was the one that was formally tested). I've rewritten the others; they weren't hairy enough before. They now work, but I'd not recommend them. This answer assumes you are using Bash or Korn shell or some other reasonably POSIX-compliant shell. It won't work with things like DOS (Windows) `cmd.exe` as the shell. – Jonathan Leffler Sep 17 '15 at 06:59
  • first solution has `!=` which should be `==`. – DarKnight Sep 20 '15 at 04:51
  • All the solutions reject the `denied` entries; and can be trivially revised to select the `denied` entries if that's what you're after. – Jonathan Leffler Sep 20 '15 at 05:15
0
awk -F- '!/denied/ {print $6}'

splits each input line in fields separated by -, ignores the lines matching denied and extracts the 6th field of the remaining lines. With you example it outputs:

216.58.209.77:443
46.28.247.89:443
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • I have tried `tail -f nohup.out | awk -F- '!/denied/ {print $6}' >> a.out ` but the output file is blank – DarKnight Sep 17 '15 at 05:58
  • Try `awk -F- '!/denied/ {print $6}' nohup.out` to check if it looks like what you want. If it does, the next step is to understand the effect of piping `tail -f nohup.out` to `awk`. What happens, probably, is that `awk` does some buffering and that you will have to wait until the buffer is flushed to see the effect. Depending on your version of `awk` there could be ways to control this flushing. With GNU Awk 4.1.1, API: 1.1 (GNU MPFR 3.1.2-p3, GNU MP 6.0.0), for instance, you can try `{print $6; fflush();}`. Let us know. – Renaud Pacalet Sep 17 '15 at 06:20