How do I execute commands serially inside a shell script? - node.js

I want to write a shell script to execute some commands in sequence (the next one starts only after the previous has finished and so on). I've never written a bash script before and I couldn't find the appropriate sequence.
I know that in the terminal you do things like yarn this && yarn that && yarn other and it works but I don't know the equivalent inside a shell script.
#!/bin/sh
direnv allow
# now wait for direnv allow to finish
direnv reload
# now wait for direnv reload to finish
yarn start:server

The shell will execute each command one after another serially as written. Servers often daemonize, i.e. fork() and have the parent return. They usually have -f flag to suppress that behavior, precisely because you may want that serial behavior.

Related

Can I prevent a subsequent chained bashed command from running?

I want to prevent a bash command from executing that has been chained using ; from running while the previous command is still running.
e.g. I write and submit command a; command b, but while command a is running I change my mind and want to prevent command b from running.
I cannot use kill because the subsequent command is not actually executing. Does bash have a queue of commands that can be manipulated?
To clarify, I am sure it is possible to make a new script or something that would allow me to create a queue, but that is not what this question is about. I specifically want to know if bash can prevent commands after a semicolon from running after I've 'submitted' them.
Consider these two scripts:
runner.sh
#!/bin/bash
while true
do
next_command=$(head -1 next_commands.list)
$next_command
sleep 60 #added to simulate processing time
done
next_commands.list
id
ls
echo hello
You can modify the content of the next_commands.list file to create a type of queue of which commands should be executed next.

Run node.js twice using sh script

I created a bash script named runall.sh with this content:
#!/bin/bash
node ../app1/app.js && node ../app/app.js
I chmod +x ./runall.sh and can run it.
But only ../app1/app.js gets started.
If I run node ../app2/app.js manually it works.
The && operator in shell scripting tries to do a short-circuit AND comparison. That means that it checks to see what the result of the first command is before the second command starts. So it will wait until the first call to node terminates before calling the second one.
You probably want to background with &?
#!/bin/bash
node ../app1/app.js &; node ../app/app.js &
As #daniel said before, the command after the '&&' operator will only be called, after the first command returned from execution.
So you could send a command to the background with the '&' operator or you could probably use some sort of node.js process manager like forever.
That way your runall.sh could look like
#! /bin/bash
forever start ../app1/app.js
forever start ../app2/app.js

Why calling a script by "scriptName" doesn't work?

I have a simple script cmakeclean to clean cmake temp files:
#!/bin/bash -f
rm CMakeCache.txt
rm *.cmake
which I call like
$ cmakeclean
And it does remove CMakeCache.txt, but it doesn't remove cmake_install.cmake:
rm: *.cmake: No such file or directory
When I run it like:
$ . cmakeclean
it does remove both.
What is the difference and can I make this script work like an usual linux command (without . in front)?
P.S.
I am sure the both times is same script is executed. To check this I added echo meme in the script and rerun it in both ways.
Remove the -f from your #!/bin/bash -f line.
-f prevents pathname expansion, which means that *.cmake will not match anything. When you run your script as a script, it interprets the shebang line, and in effect runs /bin/bash -f scriptname. When you run it as . scriptname, the shebang is just seen as a comment line and ignored, so the fact that you do not have -f set in your current environment allows it to work as expected.
. script is short for source script which means the current shell executes the commands in the script. If there's an exit in there, the current shell will exit (and e. g. the terminal window will close).
This is typically used to modify the environment of the current shell (set variables etc.).
script asks the shell to fork itself, then exec the given script in the child process, and then wait in the father for the termination of the child. If there's an exit in the script, this will be executed by the child shell and thus only terminate this. The father shell stays intact and unaltered by this call.
This is typically used to start other programs from the current shell.
Is this about ClearCase? What did you do in your poor life where you've been assigned to work in the deepest bowels of hell?
For years, I was a senior ClearCase Administer. I haven't touched it in over a decade. My life is way better now. The sky is bluer, bird songs are more melodious, and my dread over coming to work every day is now a bit less.
Getting back to your issue: It's hard to say exactly what's going on. ClearCase does some wacky things. In a dynamic view, the ClearCase repository on Unix systems is hidden in the shell's environment. Now you see it, now you don't.
When you run a shell script, it starts up a new environment. If a particular shell variable is not imported, it is invisible that shell script. When you merely run cmakeclean from the command line, you are spawning a new shell -- one that does not contain your ClearCase environment.
When you run a shell script with a dot prefix like . cmakeclean, you are running that shell script in the current shell which contains your ClearCase environment. Thus, it can see your ClearCase view.
If you're using a snapshot view, it is possible that you have a $HOME/.bashrc that's changing directories on you. When a new shell environment runs in BASH (the default shell in MacOS X and Linux), it first runs $HOME/.bashrc. If this sets a particular directory, then you end up in that directory and not in the directory where you ran your shell script. I use to see this when I too was involved in ClearCase hell. People setup their .kshrc script (it was the days before BASH and most people used Kornshell) to setup their views. Unfortunately, this made running any other shell script almost impossible to do.

Robot Framework parallel command execution

I have a testcase containing multiple Execute Commands (SSH Library) which are calling different commands in Linux environment. The main thing I would like to do is to run some of them in parallel. By default Robot performs one command and after it finishes, performs the next one.
As for me it is not a good behavior, I would like to have my command executed during execution of previous one. For example:
Execute Command ./script.sh
Execute Command ./script_parallel.sh
What I would like Robot to do:
Execute script.sh
During execution perform script_parallel.sh (which will finish before script.sh finishes)
Finish script.sh
Will it be possible to use GNU Parallel?
Execute Command parallel ::: ./script.sh ./script_parallel.sh
Have you tried Start command? It starts the command in background and returns immediately. To verify successful execution of commands you need Read Command Output.

Is there a way to run a shell script as one whole task(with single PID)?

I have a shell script called run.sh. In it, I may call other shell scripts like:
./run_1.sh
./run_2.sh
.........
If I call the script by ./run.sh, I have found actually it will invoke different tasks inside the script sequentially with different PIDs(i.e., run_1.sh will be a task and run_2.sh will be another task). This disables me to kill the whole group of tasks using one "kill" command or run the whole group of tasks all in background by running "./run.sh &".
So is there a way to run the script just as one whole task?
pkill can be used for killing the children of a process, using the -P option.
pkill -P $PID
where $PID is the PID of the parent process.
You can source the run_1.sh command so that it is executed in the same shell (This could cause side effects, since now all scripts will share the same scope).
source run_1.sh
source run_2.sh

Resources