automatically running a bash script in the background - bash

I'm interested in finding out how I'm able to do the following, but automatically.
Right now I have a bash script that looks something like this:
#!/bin/sh
sass --watch htdocs/css/scss:htdocs/css --debug-info
Now, because I want to be able to run other command-line tasks at the same time as this script is running, I could just run it inside a new window, but I prefer to have it run as a background process, which I achieve by:
Hitting [ctrl] + [Z]
Running bg
Which lets me continue to use the command-line, while also seeing the output from the sass command.
I'm also able to use jobs to see what's running, and finally, fg to bring the background script to the forefront, and use [ctrl] + [c] to cancel out of it.
All of which is fine, but it's a bit long-winded - is there any way that I can edit the bash script so it will automatically run in the background, similar to what I've described above?
Thank you

$ ./script &
^--- run script in background from the get-go

An alternative to this , which I found useful is to write a function
Foo(){
Do stuff
}
and call the function and send it to the background
Foo &
All within the script, so you don't have to do
script.sh &
Instead, just invoking the script will send it to the background.

Related

Is there a way to send a running terminal command to the background AND change the output to pipe to a log file?

Sometimes when I run a log running terminal command, I'd like to send it to the background and start doing something else in the same shell. I can do this with Ctrl+Z and bg.
However, the annoying effect this has is that it keeps showing output of the above command intermittently. Instead, when I move the process to the background, I'd also like to change where the output goes as well.
Importantly, I'm asking how to do this for an already-running command - I know that do this from scratch I could do something like command arg1 arg2 &> ~/logs/output.log &.
I have used Reptyr for this in the past.
It does have its limitations (especially with GUIs / Curses) but has worked well for me.
https://linux.die.net/man/1/reptyr
You can either start a Screen session and use reptyr to grab your running process into the screen session. Or start a new bash session which is outputting to a file and then grab the running process with reptyr.

How can I run all the bash process as background?

I don't think that running a process on foreground is any way useful. So I'd like to run all process on background. Is that possible?
Also tell me if there is any problem associated with doing so.
You can adapt the code from this question: https://superuser.com/questions/175799/does-bash-have-a-hook-that-is-run-before-executing-a-command
Basically this uses the DEBUG trap to run a command before whatever you've typed on the command line. So, this:
preexec () { :; }
preexec_invoke_exec () {
[ -n "$COMP_LINE" ] && return # do nothing if completing
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
local this_command=$(HISTTIMEFORMAT= history 1);
preexec "$this_command" &
}
trap 'preexec_invoke_exec' DEBUG
Runs the command, but with & afterwards, backgrounding the process.
Note that this will have other rather weird effects on your terminal, and anything supposed to run in the foreground (command line browsers, mail readers, interactive commands, anything requiring input, etc.) will have issues.
You can try this out by just typing bash, which will execute another shell. Paste the above code, and if things start getting weird, just exit out of the shell and things will reset.
Do you mean bash script? Jush add & at the end. Example :
$ ./myscript &
While it might be possible to do something clever like suggested by #pgl, it's not a good idea. Processes running in the background don't show you their output in a useful way. So, if all processes are automatically sent to the background, your terminal will be flooded with their various standard output and standard error messages but you will have no way of knowing what came from what, your terminal will be next to useless and confusion will ensue.
So, yes there is a very good reason to keep processes in the foreground: to see what they're doing and be able to control them easily. To give an even more concrete example, any program that requires you to interact with it can't be run in the background. This includes things that ask for Continue [Y/N]? or things like sudo that ask for your password. If you just blindly make everything run int the background such commands will just silently hang.

Ctrl C does not kill foreground process in Unix

I have the following code written in a script anmed test.csh to start a GUI based application in foreground in Solaris Unix. When I run the script and want to kill the GUI process using Keyboard Ctrl + C, the process is not getting terminated. If I open the GUI application directly from the terminal, I am able to kill the process using Ctrl + C. Can someone help me understand why am I not able to kill the process invoked from a script?
#! /usr/bin/csh
# some script to set env variables
# GUI Process
cast
Then I execute the script using the following command. I am not able to terminate the vcast process using Ctrl + C command.
source test.csh
If it is being launched into its own thread then the hangup request may not get to the application. You could add a signal handler to cascade the hangup request or look at the process table to see what the process id is for the app and then kill it. This could also be scripted very easily.
You should better execute the script directly, instead of sourcing it.
1) first add #!/bin/csh at the beginning of your script,
2) set it as executable :
$ chmod u+x test.csh
3) execute it directly:
$ ./test.csh
you should be able to kill it. Anyway, consider that the problem may be related to some executable code that you are running within your script. Consider to try to debug your script by copy-pasting line after line in a terminal until you reach the point where it lags.
Another possible annoying issue can be an infinite while loop. Check for this kind of error too. Maybe you have a while loop that never gets the breaking point.
Regards

Shell Script & progressIndicator - AppleScript

What I have is an applescript app in xcode that runs a shell script. What I was hoping to do is have the progressIndicator move a certain amount when the command is "echo hello world" as an example but since all of my commands are sudo I have to put them in a shell script together and I can't just have the progressIndicator move in between commands (there are lots of them.) Is there a way to have the bar move when a certain command is started? Also, is there a way to output the log of the applescript to a textView in xcode?
You can always run the command line tool "ps" to see which processes are currently running. As such you can formulate a repeat loop and using ps can figure out which of your commands are currently running... and thus increment your progress indicator as needed.
Here's a ps command I've used to get a nice listing. You can combine this with grep to filter for your processes...
/bin/ps -Axcro user,pid,%cpu,command

Disown, nohup or & on Mac OS zsh… not working as hoped

Hi. I'm new to the shell and am working on my first kludged together script. I've read all over the intertube and SO and there are many, MANY places where disown, nohup, & and return are explained but something isn't working for me.
I want a simpler timer. The script asks for user input for the hours, mins., etc., then:
echo "No problem, see you then…"
sleep $[a*3600+b*60+c]
At this point (either on the first or second lines, not sure) I want the script OR the specific command in the script to become a background process. Maybe a daemon? So that the timer will still go off on schedule even if
that terminal window is shut
the terminal app is quit completely
the computer is put to sleep (I realize I probably need some different code still to wake the mac itself)
Also after the "No problem" line I want a return command so that the existing shell window is still useful in the meantime.
The terminal-notifier command (the timer wakeup) is getting called immediately under certain usage of the above (I can't remember which right now), then a second notification at the right time. Using the return command anywhere basically seems to quit the script.
One thing I'm not clear on is whether/how disown, nohup, etc. are applicable to a command process vs. a script process, i.e., will any of them work properly on only a command inside a script (and if not, how to initialize a script as a background process that still asks for input).
Maybe I should use some alternative to sleep?
It isn't necessary to use a separate script or have the script run itself in order to get part of it to run in the background.
A much simpler way is to place the portions that you want to be backgrounded (the sleep and following command) inside of parentheses, and put an ampersand after them.
So the end of the script would look like:
(
sleep $time
# Do whatever
)&
This will cause that portion of the code to be run inside a subshell which is placed into the background, since there's no code after that the first shell will immediately exit returning control to your interactive shell.
When your script is run, it is actually run by starting a new shell to execute it. In order for you to get your script into the background, you would need to send that shell into the background, which you can't do because you would need to communicate with its parent shell.
What you can do is have your script call itself with a special argument to indicate that it should do the work:
#! /bin/zsh
if [ "$1" != '--run' ] ; then
echo sending to background
$0 --run $# &
exit
fi
sleep 1
echo backgrounded $#
This script first checks to see if its first argument is --run. If it is not, then it calls itself ($0) with that argument and all other arguments it received ($#) in the background, and exits. You can use a similar method, performing the test when you want to enter the background, and possibly sending the data you will need instead of every argument. For example, to send just the number of seconds:
$0 --run $[a*3600+b*60+c] &

Resources