Решено: как сделать невозможным запуск 2х или более копий программы

Модератор: Модераторы разделов

truebest
Сообщения: 18
ОС: Windows xp

Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение truebest »

Собственно сабж :rolleyes: Я понимаю можно поизващаться сделав скрипт который делает ps l ax | grep имя_программы, Но как в самой программе все это сделать...???
Спасибо сказали:
watashiwa_daredeska
Бывший модератор
Сообщения: 4038
Статус: Искусственный интеллект (pre-alpha)
ОС: Debian GNU/Linux

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение watashiwa_daredeska »

Вариантов много. Например, lock file, семафоры POSIX.
Спасибо сказали:
Аватара пользователя
SLEDopit
Модератор
Сообщения: 4824
Статус: фанат консоли (=
ОС: GNU/Debian, RHEL

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение SLEDopit »

truebest писал(а):
26.04.2010 13:25
Я понимаю можно поизващаться сделав скрипт который делает ps l ax | grep имя_программы, Но как в самой программе все это сделать...???
Сделать ярлык на программу в таком духе:

Код: Выделить всё

[ ! "`ps -A | grep программа`" ] && программа
Имхо, это самый простой способ.
Или вы пишете свою программу и хотите реализовать такую фичу?

update
Блин, не посмотрел на раздел (:
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
Спасибо сказали:
truebest
Сообщения: 18
ОС: Windows xp

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение truebest »

Да я пишу свою программу, она работает с gpsd цепляется к нему и с gps в бд sqlite ложит инфу, В кронде есть скрипт который проверяет если родной вифи то рубится киллалом моя программа этот файл с бд кидается на сервер, естественно когда нет родной сети то запускается из кронда. Я также понимаю что можно потупому, если файл бд используется вторая копия обламавшись закроется... Попробовал так...неполучается

Хочется чть нибудь в мейне написать как первое условие и все...Системное) :rolleyes:

Спасибо сказали:
Doublespace
Сообщения: 275
ОС: Debian Lenny,Squeeze,Centos

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение Doublespace »

В Qt4 решения такие есть. Но у вас на голых сях, как понимаю?
Спасибо сказали:
truebest
Сообщения: 18
ОС: Windows xp

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение truebest »

Правильно, Пишу на простом С,
Потом делаю кросскомпилящию и запускаю это на DIR-320 - D-Link

На дном форуме парня говорил...
типичная методика это создание pid файла. Монопольно создаю file.pid, при повторном запуске программа пытается пересоздать файл, но не может - значит программа уже работает.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение eddy »

Для гарантии того, что процесс - единственный, я "прибиваю" все одноименные, кроме только что запущенного:

Код: Выделить всё

//killbrothers.c
#include "killbrothers.h"
#define PROC_BASE "/proc"

int readname(char *name, pid_t pid){ // считать имя процесса из /proc/...
    char path[256], nm[512], *ptr;
    int cntr = 0, file;
    sprintf (path, PROC_BASE "/%d/cmdline", pid);
    if((file = open(path, O_RDONLY)) < 0){return 0;}
    if(read(file, nm, 512) < 1){return 0;}
    if(ptr = strrchr(nm, '/'))
        strncpy(name, ptr+1, (int)(nm-ptr+512));
    else
        strncpy(name, nm, 511);
    close(file);
    return 1;
}

int killbrothers(){
    DIR *dir;
    struct dirent *de;
    int ret = 2;
    pid_t pid, self;
    char name[512], myname[512];
    if (!(dir = opendir (PROC_BASE))){ // открываем директорию /proc
        perror(PROC_BASE);
        return 0;
    }
    self = getpid(); // свой идентификатор
    if(!readname(myname, self)) return 0; // свое имя процесса
    while ((de = readdir (dir)) != NULL){ // пока не дойдем до конца директории
    // пропустим, если директория не указывает на процесс, или указывает на self
        if (!(pid = (pid_t) atoi (de->d_name)) || pid == self)
            continue;
        if(!readname(name, pid)) continue; // считываем имя процесса
        if(strncmp(name, myname, 511) == 0){ // если оно совпадает с self
            if(kill(pid, SIGTERM) != 0) ret = 0; // убиваем
            else ret = 1;
        }
    }
    if(ret == 1)sleep(3); // подождем, пока процесс не умрет окончательно
    closedir(dir);
    return ret;
}

Код: Выделить всё

//killbrothers.h
#ifndef _KILLBROTHERS_H_
#define _KILLBROTHERS_H_
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <pwd.h>
int killbrothers();
#endif // _KILLBROTHERS_H_

Соответственно, ваша программа должна обрабатывать SIGTERM, чтобы правильно "умереть".

Если же вам нельзя грубо убивать первый экземпляр программы при запуске второго, но надо запретить запуск второго экземпляра, можете создать pid-файл и блокировать его flock'ом.
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение sash-kan »

чуть-чуть информации: http://stackoverflow.com/questions/688343/...id-file-on-unix
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
truebest
Сообщения: 18
ОС: Windows xp

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение truebest »

Eddy видел только что это, посмотрю попробую... Интересно у меня проблем не возникнет, из за того что я ее в своем приложении fork и execv делаю...

Код: Выделить всё

signal (SIGTERM, die);
    signal (SIGQUIT, die);
    signal (SIGINT, die);
    signal (SIGCHLD, chld_handler);

static void die(void)
{
    /* Ignore signals. */
    //(void)signal(SIGINT,SIG_IGN);
    //(void)signal(SIGHUP,SIG_IGN);

    /* We're done talking to gpsd. */
    (void)echo();
    //(void)endwin();
    (void)print_gpx_footer();
    (void)gps_close(gpsdata);

    /* Bye! */
    exit(0);
}

static void print_gpx_footer(void)
{
    sqlite3_close(db);
    (void)fclose(stdout);
}

Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение sash-kan »

p.s. но вообще разруливается это по-другому. в том же крон-задании напишите что-то вроде:
kill -0 $(cat /var/run/myprog.pid) || (myprog & echo $! > /var/run/myprog.pid)
если программа сама демонизируется, то замените «myprog &» просто на «myprog;»

вот, нашёл аналогичную по смыслу тему: Узнать PID
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение eddy »

truebest писал(а):
26.04.2010 18:12
Интересно у меня проблем не возникнет, из за того что я ее в своем приложении fork и execv делаю...

Если делаете execv, то прибивать надо не по pid'у, а по ppid'у. Т.е. по любому придется вам родительский pid где-то хранить (если у вас родительский процесс после форка отмирает).
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
truebest
Сообщения: 18
ОС: Windows xp

Re: Решено: как сделать невозможным запуск 2х или более копий программы

Сообщение truebest »

Вобщем мужики сделал так

Код: Выделить всё

static char *pid_file = "/var/run/cgps.pid";

static void die(int sig UNUSED)
{
    (void)print_gpx_footer();
    (void)gps_close(gpsdata);
    (void)unlink(pid_file);
      printf("PZDC \n");
        /* Bye! */
       exit(0);
}

main
{
FILE *fp;

    fp = fopen(pid_file, "r");
    if (fp == 0 )
    {
    printf("Can not open file, tru Create him\n");

    if ((fp = fopen(pid_file, "w")) != NULL) {
        (void)fprintf(fp, "%u\n", (unsigned int)getpid());
        (void)fclose(fp);
                         }
    else {
    printf("Can not create file, exit: %s.\n", pid_file);
    exit(2);
         }
    }
    else {printf("CGPS already running, exit\n");
        exit(2);
        }

(void)signal(SIGTERM, die);
    (void)signal(SIGQUIT, die);
    (void)signal(SIGINT, die);
    (void)signal(SIGCHLD, chld_handler);
}


Вобщем пид файл создается при создании процесса и убивается при убиении процесса, если файл уже создан то процесс не запускаем, там можно еще чтение из файла делать и проверку по пиду, но и так сойдеt.
А если вырубят свет внезапно то при загрузке системы в rc.local прописал удаление этого пид файла, ну а потом загружаю свое приложение. Вобщем всем спасибо, тему можно закрывать,
Спасибо сказали: