I want to execute a command like docker exec "$(docker-compose ps -q web)" start.sh from golang script using exec.command(). The problem is getting the command inside $() to execute.
The command inside of $() is executed and replaced with its output by your shell on the command line (typically bash but can be sh or others). exec.Command is running the program directly, so that replacement isn't happening. This means you need to pass that command into bash so it will interpret and execute the command:
bash -c "docker exec \"$(docker-compose ps -q web)\" start.sh"
Code Example:
exec.Command("/bin/sh", "-c", "docker exec \"$(docker-compose ps -q web)\" start.sh")
Alternatively, you can run docker-compose ps -q web yourself, get its output and do the substitution instead of having bash do it for you.
Related
I'm working on something at the moment and just now I even wonder if what I am working on is even possible.
I want to SSH from jenkins to a shell script and use variables form a rc file that are in a git Repository. (The Shell script and rc file are in the same repo)
Nothing that I tried works and now I'm starting to wondering if it's even possible.
Here's is my local script but i get the same output on jenkins.
docker exec -it test-container bash 'sed -f <(printf "s/${DOMAIN}\.%s/www.&.${DOMAIN_SUFFIX_STAGE}/g\n" ${LANG_KEYS}) /var/www/foo/sed/test.txt > /var/www/foo/sed/new-2.txt'
No matter what I do I get this error
bash: sed -f <(printf "s/${DOMAIN}\.%s/www.&.${DOMAIN_SUFFIX_STAGE}/g\n" ${LANG_KEYS}) /var/www/foo/sed/test.txt > /var/www/foo/sed/new-2.txt: No such file or directory
And yes I can confirm that the directory is there
Here's an easier way to reproduce your problem:
$ bash "echo Hello"
bash: echo Hello: No such file or directory
This happens because the expected syntax is bash yourfile. The string you are passing is not a useful filename, so it fails.
To run a string argument as a command, you can use bash -c commandstring:
$ bash -c "echo Hello"
Hello
This makes bash interpret the parameter as a shell command to execute, instead of a filename to open.
I'd like to ask if there is a way to add a prefix before certain command. Most of the similar questions on SO regard adding prefix to the output of the command and not to the command execution itself so here is my example:
I need to connect to docker container, I'm working on Windows and use ConEmu with bash terminal so I need to use winpty prefix to be able to connect to unix terminal of the container as follows:
docker exec -it my_container bash
results in:
unable to setup input stream: unable to set IO streams as raw terminal: The handle is invalid.
so I need to use:
winpty docker exec -it my_container bash
root#0991eb946acc:/var/www/my_container#
Unfortunately If I add from the begging winpty my auto completion doesn't work so I need to firstly write docker command and then jump to beginning of command to input winpty. I'd like to have bash automatically detect whenever I run "docker exec" to add winpty prefix before it.
How to achieve that?
I know I could make an alias for
alias de='winpty docker exec'
but I would rather stay with normal docker command flow to have the autocompletion.
Write a shell function that wraps docker. If it's a docker exec command call winpty, otherwise use command to fall back to the underlying docker binary.
docker() {
if [[ ${1:-} == exec ]]; then
(set -x; winpty docker "$#")
else
command docker "$#"
fi
}
I put the set -x in there so it'll print when winpty is being invoked, that way there's no hidden magic. I like to be reminded when my shell is doing sneaky things.
$ docker exec -it my_container bash
+ winpty docker exec -it my_container bash
root#0991eb946acc:/var/www/my_container#
I'm not familiar with winpty but I expect winpty docker will call the docker binary and not this shell function. But if I'm wrong you're in trouble cause it'll the function will call itself over and over in an endless recursive loop. Yikes! If that happens you can use which to ensure it calls the binary.
docker() {
if [[ ${1:-} == exec ]]; then
(set -x; winpty "$(which docker)" "$#")
else
command docker "$#"
fi
}
If you're wondering about the shell syntax:
${1} is the function's first argument.
${1:-} ensures you don't get an "unbound variable" error on the off-chance that you have set -u enabled to detect unset variables.
"$#" is an array of all the function's arguments.
I want to write a shell script that enters into a running docker container, edits a specific file and then exits it.
My initial attempt was this -
Create run.sh file.
Paste the following commands into it
docker exec -it container1 bash
sed -i -e 's/false/true/g' /opt/data_dir/gs.xml
exit
Run the script -
bash ./run.sh
However, once the script enters into the container1 it lands to the bash terminal of it. Seems like the whole script breaks as soon as I enter into the container, leaving parent container behind which contains the script.
The issue is solved By using the below piece of code
myHostName="$(hostname)"
docker exec -i -e VAR=${myHostName} root_reverse-proxy_1 bash <<'EOF'
sed -i -e "s/ServerName .*/ServerName $VAR/" /etc/httpd/conf.d/vhosts.conf
echo -e "\n Updated /etc/httpd/conf.d/vhosts.conf $VAR \n"
exit
I think you are close. You can try something like:
docker exec container1 sed -i -e 's/false/true/g' /opt/data_dir/gs.xml
Explanations:
-it is for interactive session, so you don't need it here.
docker can execute any command (like sed). You don't have to run sed via bash
I am trying to do the following:
if ps aux | grep "[t]ransporter_pulldown.py" > /dev/null
then
echo "Script is already running. Skipping"
else
exec "sudo STAGE=production $DIR/transporter_pulldown.py" # this line errors
fi
$ sudo STAGE=production $DIR/transporter_pulldown.py works on the command line, but in a bash script it gives me:
./transporter_pulldown.sh: line 9:
exec: /Users/david/Desktop/Avails/scripts/STAGE=production
/Users/david/Desktop/Avails/scripts/transporter_pulldown.py:
cannot execute: No such file or directory
What would be the correct syntax here?
sudo isn't a command interpreter thus its trying to execute the first argument as a command.
Instead try this:
exec sudo bash -c "STAGE=production $DIR/transporter_pulldown.py"
This creates uses a new bash processes to interpret the variables and execute your python script. Also note that $DIR will be interpreted by the shell you're typing in rather than the shell that is being executed. To force it to be interpreted in the new bash process use single quotes.
I'm writing a bash script that starts the tcsh interpreter as a login shell and has it execute my_command. The tcsh man page says that there are two ways to start a login shell. The first is to use /bin/tcsh -l with no other arguments. Not an option, because I need the shell to execute my_command. The second is to specify a dash (-) as the zeroeth argument.
Now the bash exec command with the -l option does exactly this, and in fact the following works perfectly:
#!/bin/bash
exec -l /bin/tcsh -c my_command
Except... I can't use exec because I need the script to come back and do some other things afterwards! So how can I specify - as the zeroeth argument to /bin/tcsh without using exec?
You can enclose the exec command into a sub-shell of your script.
#!/bin/bash
(exec -l /bin/tcsh -c my_command)
# ... whatever else you need to do after the command is done
You can write a wrapper (w.sh) script that contains:
#!/bin/bash
exec -l /bin/tcsh -c my_command
and execute w.sh in your main script.