Perl 简明教程
Perl - Process Management
您可以使用 Perl 以各种方式来创建新进程来满足您的要求。本教程将列出创建和管理 Perl 进程的一些重要且最常用的方法。
-
您可以使用特殊变量 $$ 或 $PROCESS_ID 来获取当前进程 ID。
-
使用上述任何方法创建的每个进程都维护自己的虚拟环境,也在 %ENV 变量中。
-
exit() 函数总是仅退出执行此函数的子进程,并且主进程整体不会退出,除非所有正在运行的子进程已经退出。
-
所有打开的句柄都已在子进程中进行 dup()-ed,因此关闭一个进程中的任何句柄不会影响其他句柄。
Backstick Operator
执行任何 Unix 命令的最简单方法是使用反向引号运算符。只需将您的命令放在反向引号运算符内,这样便会执行该命令并返回结果,该结果可以如下存储 −
#!/usr/bin/perl
@files = `ls -l`;
foreach $file (@files) {
print $file;
}
1;
执行上述代码时,它会列出当前目录中所有的文件和目录 −
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,但您可以使用重定向运算符 > 将其重定向到任何文件 −
#!/usr/bin/perl
system( "ls -l")
1;
执行上述代码时,它会列出当前目录中所有的文件和目录 −
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 环境变量时,请小心。尝试以下三个场景 −
#!/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 中的设置产生以下结果。
/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()。
fork() 函数用于克隆当前进程。此调用创建在同一位置运行相同程序的新进程。它向父进程返回子 pid,向子进程返回 0,或者在 fork 未成功时返回 undef。
你可以在进程中使用 exec() 函数,启动所请求的可执行程序,该程序将在独立的进程区域中执行,而 exec() 会等到它完成才退出,并带有与该进程相同的退出状态。
#!/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;
当以上代码执行后,它将产生以下结果 −
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”来避免这种情况,如下所示:-
#!/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;
当以上代码执行后,它将产生以下结果 −
Printed by parent process
Printed by child process
Tue Sep 17 15:44:07 CDT 2013
Completed process id: -1