Как программа Linux может узнать, как она была запущена: из командной строки?или cron или что-то еще? - PullRequest
0 голосов
/ 27 января 2011

Субъект говорит сам за себя: программе, работающей под Linux, нужно знать, как она была запущена. Как это сделать?

Спасибо!

- Пит

Ответы [ 7 ]

3 голосов
/ 27 января 2011

При запуске из командной строки обычно, по крайней мере, один из стандартных файловых дескрипторов является терминалом, и даже если нет, обычно существует управляющий терминал.Обычно это не так при запуске из cron.

if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO))
     puts("One of my standard file descriptors is a terminal");

int fd = open("/dev/tty", O_RDWR);
if (fd != -1) {
    puts("I have a controlling terminal");
    close(fd);
}

Существуют и другие различия, такие как окружение и т. Д., Но ни одно из них не является надежным.(Даже эти getppid решения не обязательно будут работать - cron, вероятно, начинает свою работу внутри sh.)

2 голосов
/ 27 января 2011

Я думаю, вы, возможно, ищете решение проблемы, которой не должно быть.Программе должно быть все равно, кто ее запустил.Вы можете использовать переменные окружения и ключи командной строки, чтобы изменить ожидаемое поведение вашего приложения.

Если вы должны знать, как запускается приложение, вы можете взломать что-нибудь вместе, используяps, но я бы не советовал.

1 голос
/ 27 января 2011

Если вы в буквальном смысле хотите знать, что вы используете «cron», вы можете получить идентификатор родительского процесса, а затем заглянуть в / proc, чтобы найти имя родительского процесса. Например:

#!/bin/sh 
PARENT_PID=`ps -p $$ -o ppid=` 
PARENT_CMD=`cat /proc/$PARENT_PID/cmdline` 
echo "parent = $PARENT_PID $PARENT_CMD"
1 голос
/ 27 января 2011

Эй, в Linux, как и в любой Unix-подобной системе, каждый процесс является (под) -диткой процесса init. Для просмотра этого дерева вызовов просто используйте команду ps.

Например: ps -ejH дает вам хорошее дерево вызовов

для дальнейших опций вывода смотрите справочную страницу ps.

1 голос
/ 27 января 2011

Вы можете получить идентификатор родительского процесса, чтобы увидеть, с чего началась программа.Если программа была вызвана из cron, вы можете пройти таблицу процессов через PID к оболочке, разветвленной cron и самим cron:

getppid(3) - Linux man page

Name

getppid - get the parent process ID

Synopsis

#include <unistd.h>

pid_t getppid(void);

Description

The getppid() function shall return the parent process ID of the calling process.

Return Value

The getppid() function shall always be successful and no return value is reserved to indicate an error.
1 голос
/ 27 января 2011

Первым аргументом программы обычно является команда, используемая для ее запуска.

Пример в bash:

$ cat /tmp/argv0.sh
echo $0
$ bash /tmp/argv0.sh
/tmp/argv0.sh
$ cd /tmp/ && bash ./argv0.sh
./argv0.sh
0 голосов
/ 02 сентября 2012

Вот что я использую, чтобы определить родителя процесса среди cron, at и интерактивного сеанса.По какой-то причине cron появляется в ps, а at - нет.at отображается в дереве процессов, а cron - нет.Таким образом, требуется несколько тестов, чтобы определить родителя

#!/bin/sh -

SESSION_ID=$(ps -j h $$ | awk '{print $3}')         # Get session id
# look for atd in the process table
PS=$(ps -s $SESSION_ID | sed -n '/atd/p' | sed -e '1q')
[ -n "$PS" ] && PARENT='AT daemon'              # if found

# look for CRON in the process table
PS=$(ps aux | grep $PPID | grep -v grep | grep CRON)
[ -n "$PS" ] && PARENT='CRON daemon'            # if found

# look for the tty in the process table
TTY=$(ps -j h $$ | awk '{print $4}')
[ "$TTY" == '?' ] || PARENT='Interactive shell'     # if found
...