skip to Main Content

I am trying to accomplish the following in one line:

<command> | xargs -I {} grep {} <(other command)>

I have a Kubernetes cluster which is running Redis and many other applications. I want to find out which applications (pods in this case) are connected to Redis.

This can be broken down in two steps.

  • Getting the list of IPs connected to Redis.
  • Get the pod names that holds those IPs.

I got the list of IPs with the following command:

$ kubectl exec -it redis -- redis-cli -a <redis-auth> client list | tail -n +2 | awk -F '[:= ]' '{ print $4 }' | sort | uniq > test.txt
$ cat test.txt
10.52.1.194
10.52.1.91
10.52.2.44
10.52.3.223
127.0.0.1

And I can also get the pod names with the following command:

$ grep -f test.txt <(kubectl get pods -o wide)
app1              1/1     Running     0          9d      10.52.1.91    node-8    <none>           <none>
app2              2/2     Running     0          79d     10.52.2.44    node-14   <none>           <none>
app3              2/2     Running     2          79d     10.52.1.194   node-11   <none>           <none>
app4              1/1     Running     0          5d10h   10.52.3.223   node-30   <none>           <none>

I want to accomplish both of these in one line. I tried the following:

$ kubectl exec -it redis -- redis-cli -a <redis-auth> client list | tail -n +2 | awk -F '[:= ]' '{ print $4 }' sort | uniq | xargs -t -I{} grep {} <(kubectl get pods -o wide)

it prints the following commands (that should be performed) but only performs the the first command:

grep 10.52.1.194 /dev/fd/63
app3              2/2     Running     2          79d     10.52.1.194   node-11   <none>           <none>
grep 127.0.0.1 /dev/fd/63
grep 10.52.1.91 /dev/fd/63
grep 10.52.2.44 /dev/fd/63
grep 10.52.3.223 /dev/fd/63

How can I accomplish this in one line. Also, I am aware that I can give an name to each client that is connecting to Redis but it requires changing the application code which I can’t do right now.

Edit:

The one-liner given by me actually partially works as in it only performs the first grep ... instead of all the grep ... commands. Can anyone explain what am I doing wrong here?

Edit2:

My hypothesis that only the first grep command works is that somehow after the first grep command, /dev/fd/63 probably points to a non-existing or empty file. Also, the following command works for some reason. Can anyone explain?

$ kubectl exec -t redis -- redis-cli -a <redis-auth> client list | tail -n +2 | awk -F '[:= ]' '{ print $4 }' | sort -u | xargs -t -I{} bash -c 'grep -w {} <(kubectl get pods -o wide)'
bash -c grep -w 10.52.1.194 <(kubectl get pods -o wide)
app3                 2/2     Running     2          80d     10.52.1.194   node-11   <none>           <none>
bash -c grep -w 10.52.1.91 <(kubectl get pods -o wide)
app1                 1/1     Running     0          10d     10.52.1.91    node-8    <none>           <none>
bash -c grep -w 10.52.2.44 <(kubectl get pods -o wide)
app2                 2/2     Running     0          80d     10.52.2.44    node-14   <none>           <none>
bash -c grep -w 10.52.3.223 <(kubectl get pods -o wide)
app4                 1/1     Running     0          6d10h   10.52.3.223   node-30   <none>           <none>

2

Answers


  1. Can you try this one :

    grep -f <(kubectl exec -t redis -- redis-cli -a <redis-auth> client list | tail -n +2 | awk -F '[:= ]' '{ print $4 }' | sort | uniq) <(kubectl get pods -o wide)
    

    If you have problems, trouble-shoot with this command first :

    cat <(kubectl exec -t redis -- redis-cli -a <redis-auth> client list | tail -n +2 | awk -F '[:= ]' '{ print $4 }' | sort | uniq)
    cat <(kubectl get pods -o wide)
    
    Login or Signup to reply.
  2. Try simply:

    kubectl exec -it redis -- redis-cli -a <redis-auth> client list | tail -n +2 | awk -F '[:= ]' '{ print $4 }' | sort | uniq | grep -f - <(kubectl get pods -o wide)
    

    Or same:

    kubectl exec -it redis -- redis-cli -a <redis-auth> client list |
        tail -n +2 |
        awk -F '[:= ]' '{ print $4 }' |
        sort |
        uniq |
        grep -f - <(kubectl get pods -o wide)
    

    Note 1: This is still one line, you could cut’n paste and even drop newlines. Just easier to re-read.

    Note 2: sort | uniq could be simplified by sort -u:

    kubectl exec -it redis -- redis-cli -a <redis-auth> client list |
        tail -n +2 |
        awk -F '[:= ]' '{ print $4 }' |
        sort -u |
        grep -f - <(kubectl get pods -o wide)
    

    But you could event write this:

    grep -f <(
        kubectl exec -it redis -- redis-cli -a <redis-auth> client list |
            tail -n +2 |
            awk -F '[:= ]' '{ print $4 }' |
            sort -u
      ) <(
        kubectl get pods -o wide
      )
    

    Could be re-writted in two lines:

    grep -f <(kubectl exec -it redis -- redis-cli -a <redis-auth> client list |
      tail -n +2|awk -F '[:= ]' '{ print $4 }' | sort -u) <(kubectl get pods -o wide)
    

    or

    grep -f <(kubectl exec -it redis -- redis-cli -a <redis-auth> client list | tail -n +2|awk -F '[:= ]' '{ print $4 }' | sort -u) <(kubectl get pods -o wide)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search