I'm trying to run some kubectl commands from within my container.
package main
import (
"fmt"
"os/exec"
)
op, err := GetPods("test-containers", "qa")
if err != nil {
fmt.Printf("\nError: %v", err)
}
fmt.Printf(op)
func GetPods(name, namespace string) (podName string, err error) {
fmt.Println("Get pod names ....")
cmd := "kubectl get pods -n " + namespace + " -o wide | grep " + name + " | awk '{print $1}' "
cmnd, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
fmt.Println("Failed to find pod name." + string(cmnd))
}
podName = string(cmnd)
return
}
My multistage Dockerfile is based on Alpine3.6 and has the kubectl binaries installed.
FROM alpine:3.6
RUN apk add --update curl wget ca-certificates unzip python py-pip openssl bash && \
apk --update add openssh-client && \
apk --update add --virtual build-dependencies python-dev libffi-dev openssl-dev build-base && \
apk add --no-cache --upgrade bash && \
pip install --upgrade pip cffi && \
pip install awscli && \
wget https://storage.googleapis.com/kubernetes-release/release/v1.15.1/bin/linux/amd64/kubectl && \
chmod u+x kubectl && mv kubectl /bin/kubectl && \
apk del build-dependencies && \
rm -rf /var/cache/apk/*
ENV HOME=/go/app/
WORKDIR /go/app
COPY --from=go-container-build /go/app/ .
ENTRYPOINT ["bash"]
When i run the container as a pod and try to execute the command ; i'm always presented with the following error:
cmd: kubectl -n qa get pods -o wide | grep test-containers | awk '{print $1}'
Failed to find pod name.exit status 2
/bin/sh: illegal option -
I have tried to use the os.exec.Command() like exec.Command("/bin/sh", "-c", cmd)
as well as exec.Command("/bin/bash", "-c", cmd)
but i've been getting similar errors.
Failed to find pod name.exit status 2
/bin/sh: illegal option -
I also tried cmnd := exec.Command(cmd)
directly ; but i get the error : Failed to find pod name.fork/exec kubectl -n qa get pods -o wide | grep test-containers | awk '{print $1}':executable file not found in $PATH
I have installed bash in the container and i always get the ouput when i run the command directly on the container shell.
/go/app # kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5946c5d67c-9l6hn 1/1 Running 0 10d
coredns-5946c5d67c-xh47v 1/1 Running 0 10d
kube-proxy-44lbd 1/1 Running 0 3d20h
kube-proxy-6stz8 1/1 Running 0 10d
kube-proxy-hdkmv 1/1 Running 0 3d20h
kube-proxy-zxxfr 1/1 Running 0 10d
i see the following shell in my container
/go/app # cat /etc/shells
# valid login shells
/bin/sh
/bin/ash
/bin/bash
I also have kubectl in the path.
/go/app # echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/go/app # ls -ltr /bin/ | grep kubectl
-rwxr--r-- 1 root root 42989600 Jul 18 2019 kubectl
/go/app # ls -ltr /bin/ | grep sh
-r-xr-xr-x 1 root root 6866 Apr 20 2017 bashbug
-rwxr-xr-x 1 root root 682128 Apr 20 2017 bash
lrwxrwxrwx 1 root root 12 Mar 6 2019 sh -> /bin/busybox
lrwxrwxrwx 1 root root 12 Mar 6 2019 fdflush -> /bin/busybox
lrwxrwxrwx 1 root root 12 Mar 6 2019 ash -> /bin/busybox
Can someone point out what is missing here and how do we solve the sh: illegal option -
issue here.
/bin/sh: illegal option -
is because you have a space after the -c
, which the arg parser interprets as /bin/sh "- "
-- ironically(?) your golang snippet is correct, but the parts of your code you pasted and the crux of your question shows the wrong syntax
One can trivially reproduce this without involving busybox or whatever
package main
import (
"fmt"
"os/exec"
)
func main() {
// c, err := exec.Command("/bin/sh", "-c", "echo -n hello | grep lo").Output()
c, err := exec.Command("/bin/sh", "-c ", "echo -n hello | grep lo").Output()
if err != nil {
ee := err.(*exec.ExitError)
panic(fmt.Errorf("c is %q and err is %q and stderr is %q", string(c), err, string(ee.Stderr)))
}
fmt.Println("OK")
}
results in panic: c is "" and err is "exit status 2" and stderr is "/bin/sh: - : invalid option\n
and if one swaps the commented lines, it prints OK