Perl 简明教程
Perl - Process Management
您可以使用 Perl 以各种方式来创建新进程来满足您的要求。本教程将列出创建和管理 Perl 进程的一些重要且最常用的方法。
You can use Perl in various ways to create new processes as per your requirements. This tutorial will list down few important and most frequently used methods of creating and managing Perl processes.
-
You can use special variables $$ or $PROCESS_ID to get current process ID.
-
Every process created using any of the mentioned methods, maintains its own virtual environment with-in %ENV variable.
-
The exit() function always exits just the child process which executes this function and the main process as a whole will not exit unless all running child-processes have exited.
-
All open handles are dup()-ed in child-processes, so that closing any handles in one process does not affect the others.
Backstick Operator
执行任何 Unix 命令的最简单方法是使用反向引号运算符。只需将您的命令放在反向引号运算符内,这样便会执行该命令并返回结果,该结果可以如下存储 −
This simplest way of executing any Unix command is by using backstick operator. You simply put your command inside the backstick operator, which will result in execution of the command and returns its result which can be stored as follows −
#!/usr/bin/perl
@files = `ls -l`;
foreach $file (@files) {
print $file;
}
1;
执行上述代码时,它会列出当前目录中所有的文件和目录 −
When the above code is executed, it lists down all the files and directories available in the current directory −
drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root 574 Sep 17 15:16 index.htm
drwxr-xr-x 3 544 401 4096 Jul 6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root 71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy
The system() Function
您还可以使用 system() 函数执行任何 Unix 命令,其输出将输出到 perl 脚本的输出中。默认情况下,它是屏幕,即 STDOUT,但您可以使用重定向运算符 > 将其重定向到任何文件 −
You can also use system() function to execute any Unix command, whose output will go to the output of the perl script. By default, it is the screen, i.e., STDOUT, but you can redirect it to any file by using redirection operator > −
#!/usr/bin/perl
system( "ls -l")
1;
执行上述代码时,它会列出当前目录中所有的文件和目录 −
When above code is executed, it lists down all the files and directories available in the current directory −
drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
-rw-r--r-- 1 root root 574 Sep 17 15:16 index.htm
drwxr-xr-x 3 544 401 4096 Jul 6 16:49 MIME-Lite-3.01
-rw-r--r-- 1 root root 71 Sep 17 15:16 test.pl
drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy
当您的命令包含诸如 $PATH 或 $HOME 之类的 shell 环境变量时,请小心。尝试以下三个场景 −
Be careful when your command contains shell environmental variables like $PATH or $HOME. Try following three scenarios −
#!/usr/bin/perl
$PATH = "I am Perl Variable";
system('echo $PATH'); # Treats $PATH as shell variable
system("echo $PATH"); # Treats $PATH as Perl variable
system("echo \$PATH"); # Escaping $ works.
1;
执行上述代码时,它会根据 shell 变量 $PATH 中的设置产生以下结果。
When above code is executed, it produces the following result depending on what is set in shell variable $PATH.
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
I am Perl Variable
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
The fork() Function
Perl 提供 fork() 函数,它对应于同名的 Unix 系统调用。在大多数可用的 fork() 系统调用的 Unix 类似平台上,Perl 的 fork() 只需调用它。在某些平台(例如 Windows)上不可用 fork() 系统调用,可以在解释器级别构建 Perl 以模拟 fork()。
Perl provides a fork() function that corresponds to the Unix system call of the same name. On most Unix-like platforms where the fork() system call is available, Perl’s fork() simply calls it. On some platforms such as Windows where the fork() system call is not available, Perl can be built to emulate fork() at the interpreter level.
fork() 函数用于克隆当前进程。此调用创建在同一位置运行相同程序的新进程。它向父进程返回子 pid,向子进程返回 0,或者在 fork 未成功时返回 undef。
The fork() function is used to clone a current process. This call create a new process running the same program at the same point. It returns the child pid to the parent process, 0 to the child process, or undef if the fork is unsuccessful.
你可以在进程中使用 exec() 函数,启动所请求的可执行程序,该程序将在独立的进程区域中执行,而 exec() 会等到它完成才退出,并带有与该进程相同的退出状态。
You can use exec() function within a process to launch the requested executable, which will be executed in a separate process area and exec() will wait for it to complete before exiting with the same exit status as that process.
#!/usr/bin/perl
if(!defined($pid = fork())) {
# fork returned undef, so unsuccessful
die "Cannot fork a child: $!";
} elsif ($pid == 0) {
print "Printed by child process\n";
exec("date") || die "can't exec date: $!";
} else {
# fork returned 0 nor undef
# so this branch is parent
print "Printed by parent process\n";
$ret = waitpid($pid, 0);
print "Completed process id: $ret\n";
}
1;
当以上代码执行后,它将产生以下结果 −
When above code is executed, it produces the following result −
Printed by parent process
Printed by child process
Tue Sep 17 15:41:08 CDT 2013
Completed process id: 17777
wait() 和 waitpid() 可以作为一个 fork() 返回的伪进程 ID 来传递。这些调用将等待伪进程终止并返回它的状态。如果你使用 waitpid() 函数 fork 而不等待它的子级,你将累积僵尸。在 Unix 系统中,你可以通过将 $SIG{CHLD} 设置为“IGNORE”来避免这种情况,如下所示:-
The wait() and waitpid() can be passed as a pseudo-process ID returned by fork(). These calls will properly wait for the termination of the pseudo-process and return its status. If you fork without ever waiting on your children using waitpid() function, you will accumulate zombies. On Unix systems, you can avoid this by setting $SIG{CHLD} to "IGNORE" as follows −
#!/usr/bin/perl
local $SIG{CHLD} = "IGNORE";
if(!defined($pid = fork())) {
# fork returned undef, so unsuccessful
die "Cannot fork a child: $!";
} elsif ($pid == 0) {
print "Printed by child process\n";
exec("date") || die "can't exec date: $!";
} else {
# fork returned 0 nor undef
# so this branch is parent
print "Printed by parent process\n";
$ret = waitpid($pid, 0);
print "Completed process id: $ret\n";
}
1;
当以上代码执行后,它将产生以下结果 −
When above code is executed, it produces the following result −
Printed by parent process
Printed by child process
Tue Sep 17 15:44:07 CDT 2013
Completed process id: -1
The kill() Function
Perl kill('KILL', (Process List)) 函数可以用来终止一个伪进程,方法是向它传递 fork() 返回的 ID。
Perl kill('KILL', (Process List)) function can be used to terminate a pseudo-process by passing it the ID returned by fork().
请注意,在伪进程() 中使用 kill('KILL', (进程列表)) 通常可能导致内存泄露,因为实现伪进程的线程没有机会清除它的资源。
Note that using kill('KILL', (Process List)) on a pseudo-process() may typically cause memory leaks, because the thread that implements the pseudo-process does not get a chance to clean up its resources.
你可以使用 kill() 函数向目标进程发送任何其他信号,例如,以下内容将把 SIGINT 发送到进程 ID 104 和 102 -
You can use kill() function to send any other signal to target processes, for example following will send SIGINT to a process IDs 104 and 102 −
#!/usr/bin/perl
kill('INT', 104, 102);
1;