skip to Main Content

I was trying to create a pod using yaml file, that can run few commands as soon as it started. The yaml files looks like:

kind: Pod
apiVersion: v1
metadata:
  name: testmultiplecmds
spec:
  restartPolicy: Never
  containers:
  - name: nginxmultiplecmds
    image: nginx
    command:
    - "/bin/bash"
    - -c
    - "ls -ltr"
    - "/bin/bash"
    - -c
    args:
    - "date ; sleep 36"

but everytime I run this, it only outputs the results of /bin/bash -c ls -ltr, which is basically the first command and everything else is ignored. I tried multiple combination like:

kind: Pod
apiVersion: v1
metadata:
  name: testmultiplecmds
spec:
  restartPolicy: Never
  containers:
  - name: nginxmultiplecmds
    image: nginx
    command:
    - "/bin/bash"
    - -c
    args:
    - "date ;"
    - "sleep 30"

but in this also, it just prints out the date and does not sleep.
But when I do:

kind: Pod
apiVersion: v1
metadata:
  name: testmultiplecmds
spec:
  restartPolicy: Never
  containers:
  - name: nginxmultiplecmds
    image: nginx
    command:
    - "/bin/bash"
    - -c
    args:
    - "date ; sleep 30"

it works.

So my question is, Why we cannot run multiple commands (specified in different lines as different items not under single string) even though commands and args takes []String and if we cannot run multiple commands, then why they take []String, they should simply take String?

2

Answers


  1. It works fine.

    kind: Pod
    apiVersion: v1
    metadata:
      name: testmultiplecmds
    spec:
      restartPolicy: Never
      containers:
      - name: nginxmultiplecmds
        image: nginx
        command: ["/bin/bash", "-c"]
        args: ["date; sleep 30"]
    

    ["/bin/bash", "-c"] meaning run a bash to execute following instructions. And passed commands by args. The args are then passed as commands to the bash. Commnads are separated in args by semicolon.

    update

    for multiline you can give args like this way, every command should end with a semicolon.

    args:
       - date;
         sleep 10;
         echo done;
    
    Login or Signup to reply.
  2. The issue you describes is caused by the mere fact of how bash works, and its all documented behaviour.

    Let’s consider this example:

    command:
    - "/bin/bash"
    - -c
    - "ls -ltr"
    - "/bin/bash"
    - -c
    args:
    - "date ; sleep 36"
    

    It is equal to the following command you would run in your terminal:

    /bin/bash -c "ls -ltr" "/bin/bash" -c "date ; sleep 36"
    

    What happens is you start bash and pass arguments: -c "ls -ltr" and this instructs bash to run ls. Next argument is "/bin/bash" string that is passed to bash command which looks like its being ignored by the bash executable. So are ignored all consecutive arguments.

    Let’s have a look at what bash docs says about -c option:

    If the -c option is present, then commands are read from the first
    non-option argument command_string
    . If there are arguments after
    the command_string, the first argument is assigned to $0 and any
    remaining argu‐ ments are assigned to the positional parameters
    . The
    assignment to $0 sets the name of the shell, which is used in warning
    and error messages.

    So the arguments after the command_string are not ignored, they are passed to the command as arguments.

    ok, let’s see what happens if we echo $0 and $1 in following example:

    ➜  ~ bash -c 'echo $0 $1' -c "echo 456"
    -c echo 456
    

    Notice that string -c got assigned to $0 and "echo 456" got assigned to $1; just as described in documentation.

    Do you see now how this works?

    It’s not how pods work nor how k8s works. It’s bash specific behaviour.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search