Search code examples
containerskubectlbusybox

Output of echo in a while loop inside a busybox container does not change


I am trying to get a busybox Pod to output some logs in a JSON format every second while updating the time timestamp and the msg value for debugging purposes.

For that, I create the following hello-pod

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
 name: hello-pod
spec:
 containers:
 - name: count
   image: busybox
   args: [
    /bin/sh,
    -c,
    'i=0; while true; do echo "{\"time\":$(date +%s),\"msg\":\"This is my dummy log number $i\"}"; i=$((i+1)); sleep 1; done'
   ]
EOF

I expect the Pod to write the following to the standard output

{"time":1662474158,"msg":"This is my dummy log number 0"}
{"time":1662474159,"msg":"This is my dummy log number 1"}
{"time":1662474160,"msg":"This is my dummy log number 2"}

However, I'm getting the same log output, time stays the same and i has no value.

{"time":1662473834,"msg":"This is my dummy log number "}
{"time":1662473834,"msg":"This is my dummy log number "}
{"time":1662473834,"msg":"This is my dummy log number "}

After looking a bit at this thread, I tried updating the echo statement in the third argument with echo "{\"time\":my-time}" | sed "s/my-time/$(date +%s)/" which I expected to replace the my-time string with the new current time but I still get the same result. (The first echo as output every second)


Solution

  • If you remove the kubectl apply -f -, you will see what's being cat'd to kubectl and, I think you'll find that the variables have been substituted once when the file was generated.

    This should work:

    echo 'apiVersion: v1
    kind: Pod
    metadata:
     name: hello-pod
    spec:           
     containers:
     - name: count
       image: busybox
       args: [
        /bin/sh,
        -c,
        "i=0; while true; do echo {\"time\":$(date +%s),\"msg\":\"This is my dummy log number ${i}\"}; i=$((i+1)); sleep 1; done"
       ]' | kubectl apply --filename=-
    

    My personal preference is to avoid combining JSON [...] with YAML and to use YAML's pipe (|) to more cleanly lay out the script:

    echo 'apiVersion: v1
    kind: Pod
    metadata:
     name: hello-pod
    spec:           
     containers:
     - name: count
       image: busybox
       command:
       - /bin/sh
       - -c
       args:
       - |
         i=0
         while true
         do
           echo "{\"time\":$(date +%s),\"msg\":\"This is my dummy log number ${i}\"}"
           i=$((i+1))
           sleep 1
         done
    ' | kubectl apply --filename=-