linux - 如何在 Linux 服务结构中启动多个进程?

标签 linux bash service init.d

我尝试使用以下逻辑从 Linux 服务框架启动多个 memcached 进程:

RETVAL=0
pcount="$CACHES"
if [ ! -z "$pcount" ]; then
    while [ $pcount -gt 0 ];
    do
        (( pcount-- ))
        (( port=PORT + pcount ))
        daemon --pidfile ${pidfile}${pcount}.pid memcached -d -p $port -u $USER  -m $CACHESIZE -c $MAXCONN -P ${pidfile}${pcount}.pid $OPTIONS
        (( RETVAL=RETVAL + $? ))
    done
else
    daemon --pidfile ${pidfile}.pid memcached -d -p $PORT -u $USER  -m $CACHESIZE -c $MAXCONN -P ${pidfile}.pid $OPTIONS
    RETVAL=$?
fi

当使用命令 service memcached start 运行时,它会为循环中的每个周期创建并更新 pid 文件,但只有进程的最后一个实例保持运行。也就是说,虽然每个 /var/run/memcached/memcached(1 through 5).pid 都是使用 PID 创建和更新的;这些进程不存在。 /var/run/memcached/memcached0.pid 也会被创建和更新,并且 PID 指向正在运行的进程。

我打开了跟踪,可以看到循环被执行并且进程调用被执行;但是该进程没有启动(或者可能启动并立即终止,所以我不认为它已经启动)。

另一方面,直接作为 /etc/init.d/memcached start 运行此脚本会导致所有进程正确启动。

有人可以帮助我理解为什么 service 框架阻止除最后一个实例之外的其他实例的启动吗?

最佳答案

根据 @nos 的建议,我添加了 strace -f 来跟踪 service memcached start 操作期间的调用。我比较了不成功/终止的进程和成功进程之间的跟踪调用。我发现的唯一显着差异是:

< bind(26, {sa_family=AF_INET, sin_port=htons(11216), sin_addr=inet_addr("0.0.0.0")}, 16) = -1 EACCES (Permission denied)
< dup(2)                                  = 27
< fcntl(27, F_GETFL)                      = 0x8002 (flags O_RDWR|O_LARGEFILE)
< fstat(27, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
< ioctl(27, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff20d5d780) = -1 ENOTTY (Inappropriate ioctl for device)
< mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5dae958000
< lseek(27, 0, SEEK_CUR)                  = 0
< write(27, "bind(): Permission denied\n", 26) = 26
< close(27)                               = 0
< munmap(0x7f5dae958000, 4096)            = 0
< close(26)                               = 0
< dup(2)                                  = 26
< fcntl(26, F_GETFL)                      = 0x8002 (flags O_RDWR|O_LARGEFILE)
< fstat(26, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0
< ioctl(26, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fff20d5d730) = -1 ENOTTY (Inappropriate ioctl for device)
< mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5dae958000
< lseek(26, 0, SEEK_CUR)                  = 0
< write(26, "failed to listen on TCP port 112"..., 54) = 54
< close(26)                               = 0
< munmap(0x7f5dae958000, 4096)            = 0
< exit_group(71)                          = ?
---
> bind(26, {sa_family=AF_INET, sin_port=htons(11211), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
> listen(26, 1024)                        = 0
> epoll_ctl(3, EPOLL_CTL_ADD, 26, {EPOLLIN, {u32=26, u64=26}}) = 0
> socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = 27
> fcntl(27, F_GETFL)                      = 0x2 (flags O_RDWR)
> fcntl(27, F_SETFL, O_RDWR|O_NONBLOCK)   = 0
> setsockopt(27, SOL_IPV6, IPV6_V6ONLY, [1], 4) = 0
> setsockopt(27, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> setsockopt(27, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
> setsockopt(27, SOL_SOCKET, SO_LINGER, {onoff=0, linger=0}, 8) = 0
> setsockopt(27, SOL_TCP, TCP_NODELAY, [1], 4) = 0
> bind(27, {sa_family=AF_INET6, sin6_port=htons(11211), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
> listen(27, 1024)                        = 0
> epoll_ctl(3, EPOLL_CTL_ADD, 27, {EPOLLIN, {u32=27, u64=27}}) = 0
> socket(PF_NETLINK, SOCK_RAW, 0)         = 28
> bind(28, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 0
> getsockname(28, {sa_family=AF_NETLINK, pid=31943, groups=00000000}, [12]) = 0
> gettimeofday({1393735036, 191154}, NULL) = 0
> sendto(28, "\24\0\0\0\26\0\1\3|\265\22S\0\0\0\0\0\0\0\0", 20, 0, {sa_family=AF_NETLINK, pid=0, groups=00000000}, 12) = 20
> recvmsg(28, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"0\0\0\0\24\0\2\0|\265\22S\307|\0\0\2\10\200\376\1\0\0\0\10\0\1\0\177\0\0\1"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 108
> recvmsg(28, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"@\0\0\0\24\0\2\0|\265\22S\307|\0\0\n\200\200\376\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 128
> recvmsg(28, {msg_name(12)={sa_family=AF_NETLINK, pid=0, groups=00000000}, msg_iov(1)=[{"\24\0\0\0\3\0\2\0|\265\22S\307|\0\0\0\0\0\0\1\0\0\0\24\0\1\0\0\0\0\0"..., 4096}], msg_controllen=0, msg_flags=0}, 0) = 20
> close(28)                               = 0
> socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 28

顶部 (<) 来自终止的进程,底部 (>) 来自最后一个(成功)进程。很明显,由于缺乏绑定(bind)到端口的权限,该进程正在终止。进一步观察,我意识到 SELinux 被设置为 ENFORCE,这阻止了 memcached 服务绑定(bind)到 11211(默认端口)以外的端口。

据我所知,当我在没有 service 命令的情况下运行它时,该行为只是进程(而不是服务)的行为,因此未强制执行绑定(bind)。

关闭SELinux的ENFORCED模式,service memcached start命令开始工作!

关于linux - 如何在 Linux 服务结构中启动多个进程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22107559/

相关文章:

linux - 加拿大 Cross binutils To ARM

java - 作为 Windows 服务运行时的 Tomcat 日志记录

java - Process.= Runtime.getRuntime().exec() 不适合我

linux - 仅使用 bash/标准 Linux 命令去除字符串中的单引号和双引号

bash - 为什么我不能使用 getopt 在选项和可选参数之间留一个空格?

bash - 只想执行shell脚本

android - 使用服务在后台传输通话记录

linux - Kaltura 缺少 Sphinx 服务?

linux - 将自定义硬件与一个输入接口(interface)以在/proc 中某处进行切换的最简单方法是什么?

linux - 将 & 翻译成 %20%26%20