用了这么些日子的linux/unix系统,也和别人一起合作开发了不少程序,发现高手都喜欢在命令行上操作,而且控制程序的运行偏好于使用脚本,加上参数如:start、restart、stop等。

后来自己开发程序,也越来越觉得这样是个好的方法:

1)节省时间,一键操作一系列步骤,需要记住的操作只有一两个。

2)降低出错概率,一次成功,次次成功。

3)提高通用性,同一套启动脚本的代码,可以被用在不同的程序上,需要修改的仅仅是待执行的程序命令。这也在另一个方面说明在命令行上操作程序的好处(其实每个linux程序归根到底都得在命令行上执行)。

4)通过启动脚本,可以做更多的控制,比如一次只运行一个程序实例,把输出的信息重定向到日志文件中,查看状态,结束进程等。

5)可以和别的命令结合使用。

具体而言,linux的系统服务大多通过start|stop这类方式操作。在目录/etc/init.d中放着linux服务的启动脚本,在安装系统时,会把一些服务的启动脚本放在这个目录下。

同时,根据系统运行级别的不同,linux会运行/etc/rc$level.d/目录下的启动脚本。

http://www.360doc.com/content/12/0820/17/9336047_231349272.shtml

http://blog.csdn.net/acs713/article/details/7322082

有清楚的介绍。总结起来就是,系统启动时,会根据运行级别,运行/etc/rc$level/下的脚本;而这些启动脚本都是软连接到/etc/init.d/目录下的启动脚本;也就是说/etc/init.d/里的脚本才是真正的启动脚本,rc*.d/只是分了个类;所以,如果想要单独操作某个服务,应当先到/etc/init.d/中去寻找。

在个人开发中,具体实践起来是(我使用的是perl):

1. 创建一个配置文件daemon.conf。这个文件是用来记录需要运行的命令,一行一个命令。

2. 创建一个startup.pl启动脚本。脚本有三个参数

## get first argument
my $cmd = shift(@ARGV);
switch ($cmd) {
case "start" { start() }
case "restart" { restart() }
case "stop" { stop() }
else { usage() }
}

3. 启动之后,会创建一个文件daemon.proc记录进程信息

my $PROCESS_FILE = "daemon.proc";
my $PROCESS_CONF = "daemon.conf";

如果是start命令,则首先判断是不是已经在运行中,如果不是,则先创建daemon.proc文件,并加锁。加锁的目的是防止同时运行startup.pl文件。

flock函数是perl经常用来防止程序同时运行的方法,一般是先创建一个文件再加锁,结束时对文件解锁。不过这个加锁对有的语言可能没效果(比如java),原因待查明。。

if (-e $PROCESS_FILE) {
print "fundamental services are running. Please stop them, then try again\n";
exit ;
}
my $fh;
open ($fh, ">", $PROCESS_FILE) or die("unable to open $PROCESS_FILE");
if (flock($fh, LOCK_EX | LOCK_NB)) {
## we have the lock, launch services
my $info = load();
## form json format
my $jsonText = $json->pretty->encode($info);
print $fh $jsonText;
print "services started\n";
} else {
## fail to get the lock, must be concurrency
print "fail to get the lock of $PROCESS_FILE\n";
exit ;
}

(linux的惯例是,在/var/lock/目录下touch创建一个文件如/var/lock/subsys/httpd,用来表示已经有http实例在运行,这个文件主要是给其他进程看的)

(同时会在/var/run目录下再创建一个文件/var/run/httpd/httpd.pid,记录进程的pid,用于stop用)

(http://www.blogjava.net/jasmine214--love/archive/2010/06/25/324502.html)

(文件的应用方式不只是记录信息)

/var/lock
  锁定文件.许多程序遵循在/var/lock 中产生一个锁定文件的约定,以支持他们正在使用某个特定的设备或文件.其他程序注意到这个锁定文件,将不试图使用这个设备或文件.

然后读取要执行的命令

sub load {
## read cmds from config file
my $cmds = readFile();
## collect process info
my $info = [];
foreach my $cmd (@$cmds) {
push(@$info, launch($cmd));
}
return $info;
} sub readFile {
my $lines = [];
open (my $fh, "<", $PROCESS_CONF) or die("unable to open $PROCESS_CONF");
while (<$fh>) {
chomp($_);
if ($_ =~ m/^#/) {
next;
}
## use regular expression to extract arguments,
## especially those that are in Double quotation marks
my $fields = removeQuote($_=~/\s*(\".*?\"|\S+)\s*/g);
push (@$lines, $fields);
}
return $lines;
} sub removeQuote {
my @fields = @_;
my $res = [];
foreach my $field (@fields) {
$field =~ s/\"//g;
push(@$res, $field);
}
return $res;
}

在通过fork和exec来启动程序

sub launch {
my $cmd = shift;
my $child = fork();
if ($child > ) {
## parent
# sleep 1/4 second to ensure child is up
select(undef, undef, undef, 0.25);
my $info = {};
$info->{pid} = $child;
$info->{cmd} = $cmd;
return $info;
} else {
## child process
## set as deamon process
if (!setsid()) {
print "unable to setsid()\n";
exit ;
}
## redirect STDERR and STDOUT to /dev/null,
   ## we can also redirect them to ./log
open (STDOUT, ">/dev/null");
open (STDERR, ">&STDOUT"); eval {
exec(@$cmd);
};
print "Faied to exec() cmd:".Dumper($cmd)." $@";
exit ;
}
}

运行前:daemon.conf

./count.pl

运行后:daemon.proc

[
{
"cmd" : [
"./count.pl"
],
"pid" :
}
]

如果是stop命令,则直接读取deamon.proc,杀死相应进程

sub stop {
if (!-e $PROCESS_FILE) {
print "no services are running\n";
exit ;
}
killProcess();
} sub killProcess {
my $infoArray = Utils::SystemCalls->readJsonFile($PROCESS_FILE);
foreach my $info (@$infoArray) {
print "kill $info->{pid}\n";
print `kill - $info->{pid}`; # send SIGTERM
}
print `rm $PROCESS_FILE`;
}

kill命令会发送一个信号给目标进程, 信号使监视与控制其他进程变为有可能。对接收进程来说,如果没有设置信号处理函数,那么在接收信号后,会执行默认操作;接收进程也可以拦截信号,自行处理。参考http://www.freeoa.net/development/perl/the-signal-under-perl_2671.html

重复多次的操作,最好脚本化。perl脚本实质上也是linux bash命令的组合,只是多了一些包装和日志,这样在命令出错时,可以知道是哪个命令出错了,并停止在出错的命令处;也可以结合perl和shell两边的优点。脚本语言的选择可以从熟练度出发。shell熟练就是用shell脚本。

习惯使用命令行的好处是,linux自带大量优秀的程序,在终端上调用这些程序十分方便,而这些程序通过管道组合起来的威力更是十分强大,可以轻松地帮我们解决问题。兼具操作的简便和运行的效率。

服务器上的linux系统一般是不带图形界面的,所以基本上所有的软件都会提供一套在命令行运行的命令,有时候图形界面反应很慢,可以通过命令行控制软件,就是需要改变一下使用习惯。

linux service start|stop|restart的更多相关文章

  1. 简单的linux service(linux服务)编写,运行示例

    1.写一个简单小程序 #include<stdio.h> #include<stdlib.h> int main(int argc,char **argv) { while(1 ...

  2. linux service命令常见使用方法

    service命令,顾名思义,就是用于管理Linux操作系统中服务的命令. 1. 声明:这个命令不是在所有的linux发行版本中都有.主要是在redhat.fedora.mandriva和centos ...

  3. (转)linux service理解

    能够使用service命令进行操作的,就是已经注册成为linux的系统服务了.window中也可以注册成为系统服务的办法. service命令用的次数真不少,就是比较多的关联点,用了很多次了,还是有些 ...

  4. linux service 简单易懂贴

    service用于管理Linux操作系统中服务的命令 1.不是在所有linux发行版本中都有.主要是在redhat.fedora.mandriva和centos中. 2. 命令位于/sbin目录下,用 ...

  5. linux service命令解析(重要)

    我们平时都会用service xxx start来启动某个进程,那么它背后究竟执行了什么? 其实service的绝对路径为/sbin/service ,打开这个文件cat /sbin/service, ...

  6. Linux service进程管理

    Linux进程基本介绍: 1)在Linux中,每个执行的程序(代码)都称为一个进程.每一个进程都分配一个ID号. 2)每一个进程,都对应一个父进程,而这个父进程可以复制多个子进程.例如www服务器. ...

  7. Linux service命令

    service命令(其实与其说是命令,不如说是脚本),因为service本身就是一个脚本,这个脚本在/sbin路径下,待后续shell脚本功底好了将去认真去看看这个脚本的内容(可不能被人忽悠了.) s ...

  8. linux service

    有些东西真是难得搞懂,一旦懂了就容易记住了. 说到service 就不能不说 daemon, 他们两者看起来不相关.其实是紧密相连的两个概念. —— 就像两个同心的正五边形和正六边形放在一起时候的样子 ...

  9. linux service命令解析

      我们平时都会用service xxx start来启动某个进程,那么它背后究竟执行了什么? 其实service的绝对路径为/sbin/service ,打开这个文件cat /sbin/servic ...

随机推荐

  1. vue+node+mongoDB 火车票H5(一)---准备工作,基本配置

    前端菜鸟一枚,由于公司项目用到了vue,我虽然参与了,但是很多环境配置和流程还不是特别清楚,就想自己个人业余做个webapp看看, 对于完全新手而言,很多坑会纠结很久,所以想借此机会自己做的同时记录各 ...

  2. Setting IE11 with Group Policy Preferences

    一.Setting Home Page with Group Policy Preferences 1.Open the Group Policy Management Console and cre ...

  3. MVC4 WebAPI中如何返回一张图片

    public HttpResponseMessage Get(string imageName, int width, int height) { Image img = GetImage(image ...

  4. 2015-03-22——js常用其它方法

    Function Function.prototype.method = function (name, func) {    this.prototype[name] = func;  //此时th ...

  5. loadrunner winsocket sent buffer 乱码

    data.ws里手写的xml参数,调试脚本时一直显示乱码,解决方法如下: tools-recording options--sockets--winsock下: EBCID--translation ...

  6. unittest 单元测试框架断言方法

    unittest单元测试框架的TestCase类下,测试结果断言方法:Assertion methods 方法 检查 版本 assertEqual(a, b)  a == b assertNotEqu ...

  7. go——结构

    Go语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型.结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体定义需要使用type和struct语句.str ...

  8. LeetCode:组合总数II【40】

    LeetCode:组合总数II[40] 题目描述 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candi ...

  9. Java中的静态方法是什么?

    静态方法是使用公共内存空间的,就是说所有对象都可以直接引用,不需要创建对象再使用该方法. 例如,我创建一个类,里面有一个静态方法: class Test{ public static int z(in ...

  10. Linux 进程管理 进程优先级管理

    Linux进程优先级 Linux 是一个多用户.多任务的操作系统,系统中通常运行着非常多的进程.但是 CPU 在一个时钟周期内只能运算一条指令(现在的 CPU 采用了多线程.多核心技术,所以在一个时钟 ...