Как запустить несколько процессов внутри конструкции службы Linux?

Я пытаюсь запустить несколько процессов memcached из службы linux, используя следующую логику:

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 предотвращает запуск других экземпляров, кроме последнего?


person sujitv    schedule 28.02.2014    source источник
comment
Команда службы работает с чистой средой, у вас есть что-то особенное в ваших переменных среды? Если ничего не помогает, запустите memcached с strace -f и перенаправьте вывод в файл, чтобы понять, почему он завершается)   -  person nos    schedule 01.03.2014


Ответы (1)


Как предложил @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

Верхний (‹) относится к завершившемуся процессу, а нижний (>) — к последнему (успешному) процессу. Понятно, что процесс завершается из-за отсутствия разрешения на привязку к порту. Посмотрев дальше, я понял, что SELinux был установлен на ENFORCE, что не позволяло службе memcached привязываться к порту, отличному от 11211 (порт по умолчанию).

Насколько я мог понять, когда я запускал его без команды service, поведение было просто поведением процесса (а не службы), и, следовательно, привязка не применялась.

Отключив ENFORCED режим SELinux, команда service memcached start заработала!

person sujitv    schedule 02.03.2014