How to Ctrl-Z in Perl script - perl

I am writing a Perl script and I need to execute Unix Ctrl+Z on the script.
How can I do it in Perl ?
thanks.

From perl you can send signals to processes with the function kill, which has the same name as the Unix command line tool that does the same thing. The equivalent to Ctrl+Z is running
kill -SIGTSTP pid
you need to find out what numeric value your TSTP signal has on your system. You would do this by running
kill -l TSTP
on the command line. Let's say this returns 20
Then in your Perl script you would add
kill 20 => $$;
which will send the TSTP signal to the currently running process id ($$)
Update:
as described by daxim, you can skip the 'kill -l' part and provide the name of the signal directly:
kill 'TSTP' => $$;

In bash ctrl+z stops the current job and puts it in background with %JobId you can return to this job. I'm not sure what you mean since I thought ctrl+z is caught by bash..

Related

Does a background process complete if its parent finishes first?

I am not sure if this question is specific to Perl, but it is the language I am using. Say I launch a background process to save a web page to a local file like this:
system("curl http://google.com > output_file.html &");
I know this will launch a background process, though I'm not totally sure of the details (for example does it get its own PID?). But what's particularly important to me is, what happens if the process that launched it terminates before curl finishes downloading? Will curl be allowed to continue, or will it terminate too?
Is there any reason the solution wouldn't be to prepend the above command with nohup (nohup curl ...)? See http://linux.101hacks.com/unix/nohup-command/
Yes, your backgrounded process should complete even if the script exits first.
The system call forks, what means that at that point a new, independent, process is created as a near clone of the parent. That process is then replaced by the command to run, or by a shell that will run the command.† The system then waits for the child process to complete.
The & in the command makes sure that it is a shell that is run by the system, which then executes the command. The shell itself forks a process (subshell), in which the command is executed, and doesn't wait for it but returns right away.
At that point system's job is done and it returns control to the script.
The fate of the process forked by the shell has nothing more to do with the shell, or with your script, and the process will run to its completion.
The parent may well exit right away. See this with
use warnings;
use strict;
use feature 'say';
system("(sleep 5; echo hi) &");
say "Parent exiting.";
or, from a terminal
perl -wE'system("(sleep 3; echo me)&"); say "done"'
Once in the shell, the () starts a sub-shell, used here to put multiple commands in the background for this example (and representing your command). Keep that in mind when tracking process IDs via bash internal variables $BASHPID, $$, $PPID (here $$ differs from $BASHPID)
perl -wE'say $$; system("
( sleep 30; echo \$BASHPID; echo \$PPID; echo \$\$ ) &
"); say "done"'
Then view processes while this sleeps (by ps aux on my system, with | tail -n 10).
Most of the time the PID of a system-run command will be by two greater than that of the script, as there is a shell between them (for a backgrounded process as well, on my system). In the example above it should be greater by 3, because of an additional () subshell with mulitple commands.
This assumes that the /bin/sh which system uses does get relegated to bash.
Note: when the parent exits first the child is re-parented by init and all is well (no zombies).
† From system
Does exactly the same thing as exec, except that a fork is done first and the parent process waits for the child process to exit. Note that argument processing varies depending on the number of arguments. If there is more than one argument in LIST, or if LIST is an array with more than one value, starts the program given by the first element of the list with arguments given by the rest of the list. If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp, which is more efficient. ...
The "... starts the program given by the first element ..." also means by execvp, see exec.

How to invoke Unix "script" command in Perl?

I'm sure this is an easy fix, but I need to use "script" (and not collect standard in/out/error) for my project. I'm somewhat new to Perl, so please bear with me.
I have a Perl script that works fine. When I run it I generally type script > filename before I run Perl.
$script > file.log
bash-3.2$ perl foobar.pl
This runs fine, and when I'm done I type exit or control D to stop the script and save the file. All I'd like to do is incorporate the script command in Perl and then automatically capture the file when the program stops running (12-16 hours). The problem I have is that is I call in system("script > file.log"); and them call system("perl foobar.pl"); it hangs at the bash-3.2$ prompt. The only way to get Perl to work is control D or exit, stopping the script function.
Anyone have any idea how to fix this? While it's easy to start with script before invoking Perl, if I'm a mole and forget, I have to rerun the program (which takes a long time).
Have you considered using system("script -c 'perl foobar.pl' file.log")?

How to collect the output of man command in tcl?

Can somebody suggest me, how to collect output of man command in tcl?
I am writing :-
set hello [ man {command-name}]
and when am executing the script, the program gets halted and
man commands start running in the foreground, prompting the user
to "press RETURN" again and again till it gets completed.
You're just missing the exec command
set output [exec man cmd-name]
When you do set out [man cmd-name] in an interactive tcl session, the unknown command will intercept the 'man' command and implicitly perform an exec on it. In that scenario, 'man' somehow knows you're interactive and pipes the manpage through your $PAGER.

Can I execute a multiline command in Perl's backticks?

In Unix, I have a process that I want to run using nohup. However this process will at some point wait at a prompt where I have to enter yes or no for it to continue. So far, in Unix I have been doing the following
nohup myprocess <<EOF
y
EOF
So I start the process 'myprocess' using nohup and pipe in a file with 'y' then close the file. The lines above are effectively three seperate commands - i.e. I hit enter on the first line in UNIX, then I get a prompt where I enter 'y' and then press enter to then finally type 'EOF' and hit return again.
I want to know execute this in Perl but I am not sure how I can execute this command as it is over three lines. I don't know if the following will work....
my $startprocess = `nohup myprocess <<EOF &
y
EOF
`
Please help - thank you!
I think your proposal will work as is. If not, try replacing the redirect with a pipe:
my $startprocess = `(echo "y" | nohup myprocess) &`;
Also, depending on WHY you are doing a nohup, please look at the following pure Perl daemonizing approach using Proc::Daemon : How can I run a Perl script as a system daemon in linux?
Expect for interactive programs can be used as well.

How do I exit the command shell after it invokes a Perl script?

If I run a Perl script from a command prompt (c:\windows\system32\cmd.exe), how can I exit the command prompt after the script finishes executing.
I tried system("exit 0") inside the Perl script but that doesn't exit the cmd prompt shell from where the Perl script is running.
I also tried exit; command in the Perl script, but that doesn't work either.
Try to run the Perl script with a command line like this:
perl script.pl & exit
The ampersand will start the second command after the first one has finished. You can also use && to execute the second command only if the first succeeded (error code is 0).
Have you tried cmd.exe /C perl yourscript.pl ?
According to cmd.exe /? /C carries out the command specified by string and then terminates.
If you're starting the command shell just to run the perl script, the answer by Arkaitz Jimenez should work (I voted for it.)
If not, you can create a batch file like runmyscript.bat, with content:
#echo off
perl myscript.pl
exit
The exit will end the shell session (and as a side effect, end the batch script itself.)
You can start the program in a new window using the START Dos command. If you call that with /B then no additional window is created. Then you can call EXIT to close the current window.
Would that do the trick?
You can send a signal to the parent shell from Perl:
kill(9,$PARENT_PID);`
Unfortunately, the getppid() function is not implemented in Perl on windows so you'll have to find out the parent shell PID via some other means. Also, signal #9 might not be the best choice.