Почему процесс не является частью ожидаемого процесса group?

Функция - лучший вариант, чем расширяемый псевдоним.

grep_options=( )
grep() {
  exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"
}

Таким образом, у вас есть два варианта добавления параметров в среду:

  • Изменить массив grep_options ; это правильно поддерживает параметры с пробелами, буквальные символы глобуса и другие угловые случаи:

     grep_options + = (--exclude-dir = classes --exclude-dir = '* /. sass-cache') 
     
  • Используйте традиционную скалярную переменную GREP_OPTIONS , несмотря на ее подводные камни (см. BashFAQ # 50 , чтобы понять некоторые из них):

     GREP_OPTIONS + = '--exclude-dir = classes' 
     

Тем не менее, если вы хотите, чтобы ваши параметры отражались экземплярами grep , вызываемыми вне оболочки, ни псевдоним, ни функция не подойдут. Вместо этого вам понадобится сценарий оболочки, помещенный в ваш PATH раньше, чем настоящая команда grep . Например:

# in ~/.bash_profile
[[ -e ~/bin ]] && PATH=$HOME/bin:$PATH

... и в ~ / bin / grep :

#!/bin/bash

# load overrides to grep_options on GREP_OPTIONS from local dotfiles
source ~/.bash_profile
source ~/.bashrc

# ...and use them:
exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"

5
05.05.2017, 06:27
2 ответа

Конфликта нет; процесс по умолчанию будет находиться в уникальной группе процессов, которая является группой процессов его родителя:

$ cat pg.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
    fork();
    printf("pid=%d pgid=%d\n", getpid(), getpgrp());
}
$ make pg
cc     pg.c   -o pg
$./pg 
pid=12495 pgid=12495
pid=12496 pgid=12495
$ 

forkразделяет наш процесс на родительский(12495)и дочерний (12496), и дочерний процесс принадлежит к уникальной группе процессов родителя(12495). bashотклоняется от этого, потому что вызывает дополнительные системные вызовы:

$ echo $$
12366
$

А потом в другом терминале запускаем:

$ strace -f -o blah -p 12366

А потом обратно в первый терминал:

$./pg
pid=12676 pgid=12676
pid=12677 pgid=12676
$

Затем мы контролируем+c straceи проверяем системные вызовы:

$ egrep 'exec|pgid' blah
12366 setpgid(12676, 12676)             = 0
12676 setpgid(12676, 12676 <unfinished...>
12676 <... setpgid resumed> )           = 0
12676 execve("./pg", ["./pg"], [/* 23 vars */]) = 0
12676 write(1, "pid=12676 pgid=12676\n", 21 <unfinished...>
12677 write(1, "pid=12677 pgid=12676\n", 21 <unfinished...>

bashиспользовал вызов setpgidдля установки группы процессов, тем самым помещая наш процесс pgв группу процессов, не связанную с группой процессов оболочки.(setsid(2)— еще один способ настроить группу процессов, если вы ищете системные вызовы.)

5
27.01.2020, 20:35

Bash помещает вашу программу в собственную группу процессов как часть обработки управления заданиями. Например, из справочной страницы bash:

To facilitate the implementation of the user interface to job control, the operating system maintains the notion of a current terminal process group ID. Members of this process group (processes whose process group ID is equal to the current terminal process group ID) receive keyboard-generated signals such as SIG‐ INT. These processes are said to be in the foreground. Background processes are those whose process group ID differs from the terminal's; such processes are immune to keyboard-generated signals. Only foreground processes are allowed to read from or, if the user so specifies with stty tostop, write to the terminal. Background processes which attempt to read from (write to when stty tostop is in effect) the terminal are sent a SIGTTIN (SIGTTOU) signal by the kernel's terminal driver, which, unless caught, suspends the process.

Также часть оset -m:

Monitor mode. Job control is enabled. This option is on by default for interactive shells on systems that support it (see JOB CONTROL above). All processes run in a separate process group. When a background job completes, the shell prints a line containing its exit status.

Итак, если вы хотите получить ожидаемое поведение, вы можете:

  1. Используйте forkвнутри своего кода, чтобы создать процесс без bash.
  2. Используйте set +mдля отключения режима монитора в bash. Однако это сломает такие вещи, как fg.
5
27.01.2020, 20:35

Теги

Похожие вопросы