浅谈Linux Process status,环境锁

这两天在处理一个相应问题,一个系统希望实行命令互斥,举个例子就是如果我打开了两个命令窗口,分别在这两个窗口中运行两种操作,这些操作是互斥的,即命令2要等待命令1执行完成后再执行。

 

这看似可以用简单的锁机制来实现,但实际处理时还要判断1号窗口的进程状态,用户2不会无线等待用户1的命令执行,会去系统中查看用户1的命令执行情况,如果是正在执行则继续等待,如果这个进程被暂停或者有其他情况,则用户2可以从反馈中知道具体信息

 1 sub lock_environment {
 2     my ($self) = @_;
 3 
 4     return SUCCESS if $self->get_parent();
 5     my $process_info = $self->get_process_info();
 6 
 7     while ($self->_validate_environment_lock() == ERR_ENV_LOCKED) {
 8         printf(
 9             "%s is running cvc, PID: %s, will retry in 10 seconds, please wait...........\n",
10             $process_info->{user_id},
11             $process_info->{process_id}
12         );
13         sleep(10);
14     }
15 
16     my @ret = $self->_update_env_lock_info(
17         $$,
18         $self->get_login_id(),
19         $self->get_current_environment(),
20         strftime("%Y-%m-%d %H:%M:%S", localtime()));
21     return @ret unless $ret[0] == SUCCESS;
22 
23     return SUCCESS;
24 }
lock_environment
 1 sub _validate_environment_lock {
 2     my ($self) = @_;
 3 
 4     my $process_info = $self->get_process_info();
 5 
 6     return SUCCESS if (!$process_info);
 7 
 8     my @rets = $self->_get_process_status($process_info->{process_id});
 9 
10     my $process_detail = $rets[1];
11     my @post_process_detail;
12     foreach my $str (@$process_detail) {
13         $str =~ s/\s//g;
14         push @post_process_detail, $str;
15     }
16     my @present_pid = grep {($process_info->{process_id}.$process_info->{user_id}) eq $_ } @$process_detail;
17 
18     return ERR_ENV_LOCKED if (
19         ((scalar(@present_pid)) >0) &&
20         $process_info->{env} eq $self->get_current_environment()
21     );
22 
23     $self->unlock_environment();
24 
25     return SUCCESS;
26 
27 }
Validate_environment_lock
 1 sub _get_process_status {
 2     my ($self, $process_id) = @_;
 3 
 4     my @rets;
 5     return (ERR_PROCESS_ID) unless $process_id ;
 6 
 7     $self->_run_cmd_as(
 8         sprintf(
 9             "ps -p %s -o pid -o user",
10             $process_id
11         ),
12         sub {
13             my ($line) = @_;
14             push @rets, $line;
15 
16             $self->_log($line);
17         }
18     );
19     return (SUCCESS, \@rets);
20 }
Get_process_status
 1 sub _run_cmd_as {
 2     my ($self, $cmd, $callback, $dir) = @_;
 3 
 4     my $cmd2 = $cmd;
 5     my $run_as_user = $self->get_run_as_user();
 6     my $work_dir = $dir || $self->get_public_env_dir();
 7 
 8     # The -H switch instructs sudo to set $HOME to target users
 9     # which is expected by git
10     my @parts = split(/&&/, $cmd);
11     foreach my $p (@parts) {
12         next if $p =~ /sudo -u/;
13         $p = sprintf(
14             "sudo -u %s -H qcvc_operator %s %s",
15             $run_as_user,
16             DEFAULT_WRAPPER_PASSWORD,
17             $p
18         );
19     }
20     $cmd2 = sprintf("cd '%s' && %s ", $work_dir, join('&&', @parts));
21     return $self->_run_cmd($cmd2, $callback);
22 }
_run_cmd_as

 

 

 

具体实现上用到了一些ps的知识

 

ps aux

a = show processes for all users
u = display the process's user/owner
x = also show processes not attached to a terminal

ps -p xxx  检索pid

ps -p xxx -o stat 检索pid, report形式只有pid和stat, -o可以多参数,例如ps -p xxx -o stat -o user

ps aux |grep xxx | grep xxx 针对某些关键词检索pid

pid是可重用分配的,如果一个pid被kill,在下一某个时刻会它可能会被分配给其他的进程

 

STAT狀態位常見的狀態字符

D 无法中断的休眠状态(通常 IO 的进程);
R 正在运行可中在队列中可过行的;
S 处于休眠状态;
T 停止或被追踪;
W 进入内存交换  (从内核2.6开始无效);
X 死掉的进程   (基本很少見);
Z 僵尸进程;
< 优先级高的进程
N 优先级较低的进程
L 有些页被锁进内存;
s 进程的领导者(在它之下有子进程);
l 多进程的(使用 CLONE_THREAD, 类似 NPTL pthreads);
+ 位于后台的进程组;

 

posted @ 2015-08-07 10:35  Ray.Yang  阅读(966)  评论(0编辑  收藏  举报