perl进程管理一例
1 #!/usr/bin/perl -w 2 use strict; 3 use warnings; 4 use DBI; 5 6 #### 7 # 这里进行服务器任务管理 8 ## 9 #字符串映射函数 10 our %actions = ( 11 "check" => \&pcheck, 12 "run" => \&prun, 13 "run_nohup" => \&run_nohup, 14 "kill" => \&pkill 15 ); 16 our $home = "/var/www/html"; 17 our $public_home = "/var/www/html/public" ; 18 our $log_home = "/var/www/html/yfcloud_admin/Public/log" ; 19 20 our $host = "XXX" ; 21 our $database = "XXX" ; 22 our $db_user = "XXX"; 23 our $db_pass = "XXX"; 24 25 #程序路径 26 our $ppath = "" ; 27 #程序名 28 our $pname = "" ; 29 #日志文件 30 our $log_file = "log" ; 31 32 #检测进程状态,返回PID 33 # 如果同进程不在运行,则返回空 34 sub pcheck 35 { 36 # grep 排除perl本身的进程 37 my $cmd = "ps -ef | grep " . $pname . " | grep -v grep | grep -v perl | awk '{print \$2}'"; 38 my $ret = `$cmd` ; 39 chomp $ret; 40 #如果有多个进程PID,则返回第一个pid 41 if( $ret =~ /\n/ ){ 42 $ret = ( split /\n/, $ret )[0] ; 43 } 44 ($ret eq "") ? print 0 : print $ret ; 45 } 46 47 #结束进程,返回成功与否 48 # 0 表示成功 49 sub pkill 50 { 51 my $cmd = "killall $pname"; 52 my $ret = `$cmd`; 53 print $? ; 54 } 55 56 # 参数需要是 程序的全路径 57 # 启动进程并后台运行,并返回PID 58 # 启动进程后,需要将进程的PID及日志文件写入数据库 59 # shell输出格式如下: [1] 15758 60 sub prun 61 { 62 my $cmd = "$pname"; 63 run_exec($cmd); 64 } 65 66 # 后台以nuhup方式运行 67 sub run_nohup 68 { 69 my $cmd = "nohup $pname" ; 70 run_exec($cmd); 71 } 72 73 # 命令格式如下: perl ProcessManager.pl $pname $action 74 sub main 75 { 76 umask(0); 77 #print "begin\n"; 78 #这里接收参数并执行相应的操作 79 if( @ARGV < 2 ) 80 { 81 print "arguments error!\nusage:perl ProcessManager.pl command action\n"; 82 exit 1; 83 } 84 $pname = $ARGV[0] ; #这里使用全局变量算了 ~_~ 85 my $action = $ARGV[1] ; 86 #判断操作是否合法 87 if( $actions{$action} ){ 88 $actions{$action}->() ; 89 }else{ 90 print "undeclare action!check you action!\n"; 91 exit 1; 92 } 93 } 94 95 main(); 96 97 98 99 ############ 100 ##这里是一些工具函数 101 ############ 102 sub gettime 103 { 104 my($sec,$min,$hour,$day,$mon,$year) = (localtime(time)); 105 $mon +=1 ; 106 $day = ($day < 10 )?"0$day":$day; 107 $mon = ($mon < 10 )?"0$mon":$mon; 108 $min = ($min < 10 )?"0$min":$min; 109 110 return "$mon$day$hour$min" ; 111 } 112 113 sub run_exec 114 { 115 my $cmd = shift ; 116 #先检测文件是否存在,可执行 117 if( -x $pname ){ 118 $pname =~ m#.+/(.+)# ; #获得程序名(包括后缀名)作为日志文件名称 119 # 建立程序的日志文件目录 120 my $name = $1 ; 121 mkdir "$log_home/$name" or die("cannot create dir:$name") unless ( -e "$log_home/$name" ); 122 $log_file = "$log_home/$name/".gettime() ; 123 # print "log_file : $log_file\n"; 124 $cmd .= " > $log_file 2>&1 &"; 125 addToDB($name,$log_file); 126 my $pid = fork; 127 if (not $pid) { 128 $pid = $$; 129 print $pid ; 130 exec($cmd); #exec是异步的,执行完后就脱离perl程序了 131 } 132 }else{ 133 print "$pname cannot be excuted\n"; 134 exit 1; 135 } 136 } 137 138 # 将日志写入日志 139 sub addToDB 140 { 141 my ($progName,$log_file) = @_ ; 142 my $createtime = time ; 143 my $db_handle = DBI->connect("DBI:mysql:database=$database;host=$host", $db_user, $db_pass, {'RaiseError' => 1})|| die "Could not connect to database: $DBI::errstr"; 144 145 my $sql = "insert into log (name,log_file,createtime) values (?,?,?)"; 146 my $sth = $db_handle->prepare($sql); 147 148 $sth->execute($progName, $log_file , $createtime) or die $DBI::errstr; 149 $sth->finish(); 150 151 $db_handle->disconnect(); 152 }