почему не работает PATH, когда я добавляю в него env и хочу запустить программу под env?

Я отвечу только за Linux.

Удивительно, но в новых ядрах системный вызов ptrace , который используется strace для фактического выполнения трассировки, позволяет отслеживать процесс инициализации. На странице руководства сказано:

   EPERM  The specified process cannot be traced.  This could  be  because
          the  tracer has insufficient privileges (the required capability
          is CAP_SYS_PTRACE); unprivileged  processes  cannot  trace  pro‐
          cesses  that  they  cannot send signals to or those running set-
          user-ID/set-group-ID programs, for  obvious  reasons.   Alterna‐
          tively,  the process may already be being traced, or (on kernels
          before 2.6.26) be init(8) (PID 1).

, что подразумевает, что начиная с версии 2.6.26, вы можете отслеживать init , хотя, конечно, вы все еще должны быть root, чтобы сделать это. Бинарный файл strace в моей системе позволяет мне отслеживать init , и на самом деле я даже могу использовать gdb для подключения к init и уничтожения Это. (Когда я это сделал, система немедленно остановилась.)

ptrace не может использоваться процессом для трассировки себя, поэтому, если strace не проверит, он, тем не менее, завершится ошибкой на отслеживая себя. Следующая программа:

#include 
#include 
#include 
int main() {
    if (ptrace(PTRACE_ATTACH, getpid(), 0, 0) == -1) {
        perror(NULL);
    }
}

печатает Операция запрещена ( т.е. результат EPERM ). Ядро выполняет эту проверку в ptrace.c :

 retval = -EPERM;
 if (unlikely(task->flags & PF_KTHREAD))
         goto out;
 if (same_thread_group(task, current)) // <-- this is the one
         goto out;

Теперь два процесса strace могут отслеживать друг друга; ядро этому не помешает, и вы сами можете наблюдать за результатом. Для меня последнее, что выводит первый процесс strace (PID = 5882), это:

ptrace(PTRACE_SEIZE, 5882, 0, 0x11

, тогда как второй процесс strace (PID = 5890) вообще ничего не печатает. ps показывает оба процесса в состоянии t , что, согласно странице руководства proc (5) , означает, что трассировка остановлена.

Это происходит из-за того, что трассируемый объект останавливается всякий раз, когда он входит в системный вызов или выходит из него, а также всякий раз, когда ему собирается доставить сигнал (кроме SIGKILL ).

Предположим, что процесс 5882 уже отслеживает процесс 5890. Затем мы можем вывести следующую последовательность событий:

  1. Процесс 5890 входит в системный вызов ptrace , пытаясь отследить процесс 5882. Процесс 5890 входит в трассировку. -останавливаться.
  2. Процесс 5882 получает SIGCHLD , чтобы сообщить ему, что его трассируемый процесс 5890 остановлен. (Процесс с остановленной трассировкой выглядит так, как если бы он получил сигнал `SIGTRAP.)
  3. Процесс 5882, видя, что его трассируемый вызов выполнил системный вызов, покорно распечатывает информацию о системном вызове, который процесс 5890 собирается сделать, и аргументы. Это последний вывод, который вы видите.
  4. Процесс 5882 вызывает ptrace (PTRACE_SYSCALL, 5890, ...) , чтобы продолжить процесс 5890.
  5. Процесс 5890 выходит из остановки трассировки и выполняет свою ptrace (PTRACE_SEIZE, 5882, ...) . Когда последний возвращается, процесс 5890 переходит в режим остановки трассировки.
  6. Процесс 5882 отправляется SIGCHLD , поскольку его трассируемый объект только что снова остановился. Поскольку он отслеживается, получение сигнала приводит к переходу к остановке трассировки.

Теперь оба процесса остановлены. Конец.

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

1
08.07.2017, 20:48
3 ответа

Мне кажется, вы используете неправильный тип цитат ("" )против (""):

echo $PATH
/home/anon/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
sudo bash -c 'echo \$0 this is a test' >/opt/test.sh;sudo chmod +x /opt/test.sh
anon@masterbox:~$ export PATH=“$PATH:/opt”
anon@masterbox:~$ test.sh
bash: test.sh: command not found
anon@masterbox:~$..bashrc
anon@masterbox:~$ export PATH="$PATH:/opt"
anon@masterbox:~$ test.sh
/opt/test.sh this is a test
anon@masterbox:~$ 

Изменить :Чтобы еще больше прояснить проблему, посмотрите, что произойдет, если я сделаю это по-вашему:

$ echo $PATH
# this is correct
/home/anon/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
$ export PATH=“$PATH:/opt” 
$ echo $PATH
# this is incorrect
“/home/anon/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/opt”
$ 

Таким образом, Bash неправильно интерпретирует переменную PATH. Кавычки Unicode не работают таким образом в системах unix. Надеюсь, что это ответ на ваш вопрос.

2
27.01.2020, 23:33

Для меня есть 2 группы файлов, в которых можно определить $PATH:
1. Файлы bash, такие как ~/.profile, ~/.bashrc и их эквиваленты /etc
2. /etc/enviroment и ~/.pam _окружение
Некоторые из этих мест являются глобальными для всех пользователей, а некоторые зависят от пользователя.
Я рекомендую вам написать команду, которую вы использовали, в одном из этих мест, помня, что файлы с~работают только с пользователем, который использует домашний каталог, в котором находится файл.
Также помните, если вы пропишете путь, например, ~/.bashrc, будучи, например, пользователем Robertus, если вы измените на root, путь изменится на root, следуя его собственному ~/.bashrc и компании..

Надеюсь, мой ответ был вам полезен

0
27.01.2020, 23:33

Работает ли корова, если запустить ее как :/opt/cow? Если нет, проверьте режим файла «корова»; он должен иметь установленный исполняемый бит. Если это не так, используйте:chmod +x /opt/cow

0
27.01.2020, 23:33

Теги

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