Escaping Docker attach one started from bash script - bash

I'm running Docker commands from a management script and one of the commands I use is attach.
Attaching works fine but I can't seam to leave the output either by pressing CTRL+C or CTRL+P/CTRL+Q.
My theory is that the key signals are not fetched by Docker since bash is running front of it.
Is this correct? And how do I solve this?

Related

Can't terminate node(js) process without terminating ssh server in docker container

I'm using a Dockerfile that ends with a CMD ["/start.sh"]:
#!/bin/bash
service ssh start
/usr/bin/node /myApp/app.js
if for some reason i need to kill the node process, the ssh server is being closed as well (forces me to reboot the container to reconnect).
Any simple way to avoid this behavior?
Thank You.
The container exits as soon as main process of the container exits. In your case, the main process inside the container is start.sh shell script. The start.sh shell script is starting the ssh service and then running the nodejs process as child process. Once the nodejs process dies, the shell script exits as well and so the container exits. So what you can do is to put the nodejs process in background.
#!/bin/bash
service ssh start
/usr/bin/node /myApp/app.js &
# Need the following infinite loop as the shell script should not exit
while do:
sleep 2
done
I DO NOT recommend this approach though. You should have only a single process per container. Read the following answers to understand why -
Running multiple applications in one docker container
If you still want to run multiple processes inside container, there are better ways to do it like using supervisord - https://docs.docker.com/config/containers/multi-service_container/

Run two executables in docker

I would like my container to launch two processes when it is run;
the generic "this process is runnning to keep the container awake" process (keep_awake.sh), and
node app.js
Is there any way to have both of these launch at the start, based in the dockerfile?
I'm thinking of some sort of abuse of bash, but don't know specifically which one yet.
Further complicating things, keep_awake.sh is in a directory different than app.js.
You should never need an artificial “keep this container alive” process. This is doubly true in the situation you’re describing, where you have a single long-running application process.
Best practice is for a Docker container to run a single process, and run it as a foreground job. If that process ever exits, the container will exit too — and you want this. (It’d be kind of embarrassing for your Node app to die but for you to not notice, because Docker sees that tail -f /dev/null is still up and running.)
In short, end your Dockerfile with
CMD ["node", "app.js"]
and ignore the second do-nothing process.

bash ignores & for last command in loop

I just wrote my first bash script to start some redis instances on a development server. While it is mostly working, the last opened redis instance is blocking the active terminal – though I have the trailing & sign and the other started instances aren't blocking the terminal. How would I push them all to the background?
Here's the script:
#!/bin/bash
REDIS=(6379 6380 6381 6382 6383 6390 6391 6392 6393)
for i in "${REDIS[#]}"
do
:
redis-server --port $i &
done
It sounds like your terminal is not actually blocked, your prompt just got overwritten. It's a purely cosmetic issue. Due to the way terminals work, bash doesn't know to redraw it so it looks like the command is in the foreground.
Run the script again, and blindly type lsEnter. You'll probably see that the shell responds as normal, even though you can't see the prompt.
You can alternatively just hit Enter to get bash to redraw the prompt.

start multiple docker containers with a single command line shell script (without docker-compose)

I've got 3 containers that will run on a single server, which we'll call: A,B,C
Each server has a script on the host that has the commands to start docker:
A_start.sh
B_start.sh
C_start.sh
I'm trying to create a swarm script to start them all, but not sure how.
ABC_start.sh
UPDATE:
this seems to work, with the first being output to the terminal, cntrl+C exits out of them all.d
./A_start.sh & ./B_start.sh & ./C_start.sh
swarm will not help you start them at all..., it is used to distribute the work amongst docker machines that are part of the cluster.
there is no good reason not to use docker-compose for that use case, its main purpose is to link containers properly, and bring them up, so your collection of scripts could end up being a single docker-compose up command.
In bash,
you can do this:
nohup A_start.sh &
nohup B_start.sh &
nohup C_start.sh &

How to ssh into a shell and run a script and leave myself at the prompt

I am using elastic map reduce from Amazon. I am sshing into hadoop master node and executing a script like.
$EMR_BIN/elastic-mapreduce --jobflow $JOBFLOW --ssh < hivescript.sh . It sshes me into the master node and runs the hive script. The hivescript contains the following lines
hive
add jar joda-time-1.6.jar;
add jar EmrHiveUtils-1.2.jar;
and some commands to create hive tables. The script runs fine and creates the hive tables and everything else, but comes back to the prompt from where I ran the script. How do I leave it sshed into hadoop master node at the hive prompt.
Consider using Expect, then you could do something along these lines and interact at the end:
/usr/bin/expect <<EOF
spawn ssh ... YourHost
expect "password"
send "password\n"
send javastuff
interact
EOF
These are the most common answers I've seen (with the drawbacks I ran into with them):
Use expect
This is probably the most well rounded solution for most people
I cannot control whether expect is installed in my target environments
Just to try this out anyway, I put together a simple expect script to ssh to a remote machine, send a simple command, and turn control over to the user. There was a long delay before the prompt showed up, and after fiddling with it with little success I decided to move on for the time being.
Eventually I came back to this as the final solution after realizing I had violated one of the 3 virtues of a good programmer -- false impatience.
Use screen / tmux to start the shell, then inject commands from an external process.
This works ok, but if the terminal window dies it leaves a screen/tmux instance hanging around. I could certainly try to come up with a way to just re-attach to prior instances or kill them; screen (and probably tmux) can make it die instead of auto-detaching, but I didn't fiddle with it.
If using gnome-terminal, use its -x or --command flag (I'm guessing xterm and others have similar options)
I'll go into more detail on problems I had with this on #4
Make a bash script with #!/bin/bash --init-file as the shebang; this will cause your script to execute, then leave an interactive shell running afterward
This and #3 had issues with some programs that required user interaction before the shell is presented to them. Some programs (like ssh) it worked fine with, others (telnet, vxsim) presented a prompt but no text was passed along to the program; only ctrl characters like ^C.
Do something like this: xterm -e 'commands; here; exec bash'. This will cause it to create an interactive shell after your commands execute.
This is fine as long as the user doesn't attempt to interrupt with ^C before the last command executes.
Currently, the only thing I've found that gives me the behavior I need is to use cmdtool from the OpenWin project.
/usr/openwin/bin/cmdtool -I 'commands; here'
# or
/usr/openwin/bin/cmdtool -I 'commands; here' /bin/bash --norc
The resulting terminal injects the list of commands passed with -I to the program executed (no parms means default shell), so those commands show up in that shell's history.
What I don't like is that the terminal cmdtool provides feels so clunky ... but alas.

Resources