Exit nohup alias after completion [duplicate] - bash

I have an executable file that contains a long loop, so I want to run it in background, how do I do that with bash script in Linux?
I know one way is Ctrl + z, then I type bg, how to simulate these key pressing in bash script?

Any executable in linux can be run in the background as follows:
$ ./yourExecutable.exe&
Add the & character at end. (Assuming yourExecutable.exe is in the current working directory)
How to kill it later on?
$ ps -ax | grep yourExecutable.exe
You will get an output like:
9384 pts/7 S+ 0:00 grep yourExecutable.exe
25082 pts/7 T 0:00 yourExecutable.exe&
Kill the second process using SIGKILL. That is the one you executed in the background.
$ kill -9 25082

Related

Executing a shell with a command and returning

man bash seems to suggest that if I want to execute a command in a separate bash shell all I have to do is bash -c command:
-c string If the -c option is present, then commands are read from string.
I want to do that because I need to run a few things in different environments:
bash --rcfile ~/.bashrc.a -c mytest.a
bash --rcfile ~/.bashrc.b -c mytest.b
However, that didn't work as expected; one can see that by the number of bash shells running, for example:
$ bash
$ ps
PID TTY TIME CMD
7554 pts/0 00:00:00 bash
7573 pts/0 00:00:00 ps
28616 pts/0 00:00:00 bash
$ exit
exit
$ ps
PID TTY TIME CMD
7582 pts/0 00:00:00 ps
28616 pts/0 00:00:00 bash
$ bash -c ps
PID TTY TIME CMD
7583 pts/0 00:00:00 ps
28616 pts/0 00:00:00 bash
How should the invocation of bash should be modified so that it would start a new shell with the specified rc, execute the given command in that shell (with the env modified according to the rc), and exit back?
It's already working exactly the way you want it to. The lack of an extra process is simply due to bash's tail-call optimization.
Bash recognizes that there's no point in having a shell instance whose only job is to wait for a process and exit. It will instead skip the fork and exec the process directly. This is a huge win for e.g. var=$(ps), where it cuts the number of expensive forks from 2 to 1.
If you give it additional commands to run afterwards, this optimization is no longer valid, and then you'll see the additional process:
$ bash -c 'ps'
PID TTY TIME CMD
4531 pts/10 00:00:00 bash
4540 pts/10 00:00:00 ps
$ bash -c 'ps; exit $?'
PID TTY TIME CMD
4531 pts/10 00:00:00 bash
4549 pts/10 00:00:00 bash
4550 pts/10 00:00:00 ps
bash --rcfile ~/.bashrc.a mytest.a will already run mytest.a in a separate process. -c is for specifying a shell command directly, rather than running a script.
# NO!
bash for x in 1 2 3; do echo "$x"; done
# Yes.
bash -c 'for x in 1 2 3; do echo "$x"; done'

How to make ps command to show user, PID, terminal, CMD

I need to use command that shows all processes related to terminal. Ps -a looks good except that there is no username printed. This command prints:
PID TTY TIME CMD
26969 pts/34 0:00 man
27636 pts/2 0:00 awk
25215 pts/35 0:00 bash
I would like it to be similar to this:
PID TTY TIME CMD USER
26969 pts/34 0:00 man name
27636 pts/2 0:00 awk name
25215 pts/35 0:00 bash name
Columns order does not matter
Use:
ps a -o pid,tty,etime,cmd,user
From ps manual:
SIMPLE PROCESS SELECTION
a ... An alternate description is that this option causes ps to list all processes with a terminal (tty), or to list all processes
when used together with the x option.
STANDARD FORMAT SPECIFIERS
Here are the different keywords that may be used to control the output format (e.g. with option -o) or to sort the selected processes
with the GNU-style --sort
option.
For example: ps -eo pid,user,args --sort user
I have found that ps -af works the way I want

$> bash script.sh ... does the forked bash process in turn create a sub-shell?

If I run:
$> bash script.sh
a fork-and-exec happens to run the bash binary. Does that process execute script.sh or does it create a sub-shell in turn in the same way that
$> ./script.sh
first creates a sub-shell to execute the script?
The bash process that runs bash script.sh executes the script directly, not as a second layer of fork and exec. Obviously, individual commands within the script are forked and executed separately, but not the script itself.
You could use ps to show that. For example, script.sh might contain:
tty
echo $$
sleep 20
You could run that and in another terminal window run ps -ft tty0 (if the tty command indicated tty0), and you'd see the shell in which you ran the bash script.sh command, the shell which is running script.sh and the sleep command.
Example
In ttys000:
$ bash script.sh
/dev/ttys000
65090
$
In ttys001:
$ ps -ft ttys000
UID PID PPID C STIME TTY TIME CMD
0 2422 2407 0 9Jul14 ttys000 0:00.13 login -pfl jleffler /bin/bash -c exec -la bash /bin/bash
199484 2428 2422 0 9Jul14 ttys000 0:00.56 -bash
199484 65090 2428 0 3:58PM ttys000 0:00.01 bash script.sh
199484 65092 65090 0 3:58PM ttys000 0:00.00 sleep 20
$
You can use pstree or ps -fax to look at the process tree. In your case when specifying bash as a (forked) command with a script parameter it will not (need) to fork a subshell as running with "command file" is one mode of operation (if not used -c).
BTW: you can also use exec sh script.sh to replace your current shell process with the new sub shell.
When you call a shell script without the source (or .) command, it will run in a subshell. This is the case for your second line. If you want to run the script in the current one, you would need to use . ./script.sh.

Bash hide "killed"

I cannot see to hide the "killed" output from my script. Please help.
killall -9 $SCRIPT
I have tried:
killall -9 $SCRIPT >/dev/null 2>&1
and everyone redirect combination it seems. Thanks for the help.
* UPDATE *
The main script cannot run in the background. It outputs a bunch on information to the user while running. Thanks for the input though. Any other ideas?
Here is the desired output
HEV Terminated
administrator#HEV-DEV:~/hev-1.2.7$
Here is the current output:
HEV Terminated
Killed
administrator#HEV-DEV:~/hev-1.2.7$
It's not the script printing it, it's the shell. You can suppress it by putting it in the background and waiting for it to finish, redirecting the error from there:
./script &
wait 2>/dev/null
It looks like this can be avoided if you execute the script (including the &) in a subshell:
$ ( ./script.sh & )
$ ps
PID TTY TIME CMD
14208 pts/0 00:00:00 bash
16134 pts/0 00:00:00 script.sh
16135 pts/0 00:00:00 sleep
16136 pts/0 00:00:00 ps
$ killall script.sh
$
If I execute it (without the subshell) like ./script.sh then I get the output
[1]+ Terminated ./script.sh &>/dev/null
Try ...
(killall -9 $SCRIPT) 2>/dev/null
This executes the "killall" in a subshell and all output from that subshell is redirected, including the the "KILLED" output.
Try killall -q,--quiet don't print complaints
killall -q -9 $SCRIPT

Orphan Child (ksh Shell Script not terminating first upon CTRL-X)

I have a program (C++ Executable) on AIX 5.3 that launches a Shell Script (ksh).
When I launch the program and the shell script, i see two processes
AIX:>ps -ef | grep 3657892
u001 **3657892** 3670248 0 18:16:34 pts/11 0:00 /u0012006/bin/Launcher
u001 3723398 **3657892** 0 18:16:41 pts/11 0:00 /usr/bin/ksh /u0012006/shell/Trjt_Slds.sh -m
Now, When I do a CTRL-X key combination on the Keyboard to end and go out of the Shell Script, the main launching program (C++ Executable) process gets killed while the shell script continues to execute.
AIX:>ps -ef | grep 3723398
u001 3723398 1 106 18:16:41 pts/11 0:01 /usr/bin/ksh /u0012006/shell/Trjt_Slds.sh -m
u001 3731504 3723398 0 0:00 <defunct>
u001 3735612 3723398 0 0:00 <defunct>
u001 3739838 3723398 0 0:00 <defunct>
This is leading to the CPU Consumption going to 100% and a lot of defunct processes get launched.
Is there a way to have the AIX Shell Script terminate first when I do a CTRL-X?
Note: Launcher is broken and should be fixed. Thus, any "solution" will be a hack.
One thought is to check $PPID in various places in the script. If it is set to 1 (init), then exit the script.
I don't understand the use of control-X. That is not going to generate any tty signal. I guess that is what you want. Perhaps the tty is also in raw mode. But you might consider hooking control-X up to one of the various tty signals like SIGINT. e.g. stty intr ^X but you will also need to remember to unset it with stty intr ^C
Last, you could wrap the script in a script and use the technique to kill the child and exit. e.g. (untested)
#!/bin/ksh
# launch original program in background
/path/to/real/program "$#" &
# get child's pid
child=$!
while : ; do
# when we become an orphan
if [[ $$PPID -eq 1 ]] ; then
# kill the child and exit
kill $child
exit
fi
# poll once a second
sleep 1
done
Update
./s1 is:
#!/bin/ksh
./s2 &
sleep 10
exit
./s2 is:
#!/bin/ksh
while : ; do
if kill -0 $PPID ; then
echo still good
else
echo orphaned
exit
fi
sleep 1
done
ksh always does this. Just got bitten by this, unlike bash, ksh does not forward hup signals when you exit. if you can find the child pids you can hup them yourself.

Resources