AnxiousGuy
AnxiousGuy

Reputation: 45

How to Use Kubernetes Multiple Commands and Arguments without passing scripts

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?

Upvotes: 1

Views: 6455

Answers (2)

Matt
Matt

Reputation: 8152

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.

Upvotes: 1

Sahadat Hossain
Sahadat Hossain

Reputation: 4351

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;

Upvotes: 1

Related Questions