Как установить рабочий каталог родительского процесса?

Как показывает заголовок, мы пишем утилиту оболочки в стиле Unix U это должно быть вызвано (в большинстве случаев) из bash.

Как именно U изменить рабочий каталог bash (или родительский вообще)?

P. S. В утилита командной строки chdir преуспевает в том же самом, поэтому должен быть программный способ достижения эффекта.

7 ответов


Не делай этого.

FILE *p;
char cmd[32];
p = fopen("/tmp/gdb_cmds", "w");
fprintf(p, "call chdir(\"..\")\ndetach\nquit\n");
fclose(p);
sprintf(cmd, "gdb -p %d -batch -x /tmp/gdb_cmds", getppid());
system(cmd);

Это наверное работа, хотя обратите внимание, что Баш кэшируется и не заметит.


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

chdir который изменяет каталог в сценариях bash не является внешней утилитой, это встроенная команда.


как именно вы можете изменить рабочий каталог bash (или родитель В общем)?

Это не можно использовать любые "приемлемым" способом. Под приемлемым я подразумеваю " без возмутительно взлома вашей системы (используя gdb к примеру)" ;)

более серьезно, когда пользователь запускает исполняемый файл, дочерний процесс будет работать в его собственные среда, которая в основном скопировать of родительской среде. Эта среда содержит "переменные среды", а также "текущий рабочий каталог", просто чтобы назвать эти два.

конечно, процесс может изменить его собственные окружающая среда. Например, чтобы изменить свой рабочий каталог (например, когда вы cd xxx в вас снарядом). Но так как эта среда является скопировать, это никоим образом не изменяет среду родителя. И нет стандартного способа изменить своего родителя окружающая среда.


в качестве примечания, вот почему cd ("chdir") является внутренние shell команда, а не внешний утилиты. Если бы это было так, он не смог бы изменить рабочий каталог оболочки.

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

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


путь я решил эту должен иметь псевдоним оболочки, который вызывает сценарий и источник файла, который написал сценарий. Так, например,

function waypoint {
    python "$WAYPOINT_DIRECTORY"/waypoint.py $@ &&
    source ~/.config/waypoint/scratch.sh
    cat /dev/null > ~/.config/waypoint/scratch.sh
}

и waypoint.py создает scratch.sh выглядеть

cd /some/directory

Это все еще плохо.


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

alias cdfoo='cd theFooDir'

при работе с неинтерактивными сценариями оболочки можно создать протокол между родительским сценарием Bash и дочерним сценарием Bash. Один из способов реализации этого-позволить дочернему скрипту сохранить путь в файл (например,~/.new-work-dir). После завершения дочернего процесса родительский процесс должен будет прочитать это файл (например,cd `cat ~/.new-work-dir`).

если вы планируете использовать правило, упомянутое в предыдущем абзаце, очень часто, я бы предложил вам загрузить исходный код Bash и исправить его так, чтобы он автоматически изменял рабочий каталог на содержимое ~/.new-work-dir после каждого запуска команды. В патче вы даже можете реализовать совершенно новую встроенную команду Bash, которая соответствует вашим потребностям и реализует протокол, который вы хотите реализовать (эта новая команда, вероятно, не будет принята сопровождающие Баша). Но исправление работает для личного использования и для использования в меньшем сообществе.


я не уверен, что это"не делай этого" тоже...

спасибо весьма полезное обсуждение внутри https://unix.stackexchange.com/questions/213799/can-bash-write-to-its-own-input-stream/ ...

на tailcd утилита (для " tail-call cd"), который работает как в bash, так и под Midnight Commander позволяет использовать в сценариях, таких как

/ bin / mkcd:

mkdir "" && tailcd ""

реализация сложна, и это требуется xdotool. на tailcd команда должна быть последней командой в скрипте (это типичное требование совместимости для утилит, допускающих несколько реализаций). Он взломает входной поток bash, а именно: inserts cd <dirname> в нее. В случае Midnight Commander он дополнительно вставляет две команды клавиатуры Ctrl+O (panels on/off) и, в очень хакерской манере, использует sleep для межпроцессной синхронизации (что позорно, но это завод.)

/ bin / tailcd:

#! /bin/bash
escapedname=`sed 's/[^a-zA-Z\d._/-]/\\&/g' <<< ""`
if [ -z "$MC_TMPDIR" ] ; then
xdotool type " cd $escapedname  "; xdotool key space Return
else
(sleep 0.1; xdotool type " cd $escapedname "; xdotool key space Return Ctrl+o; sleep 0.1; xdotool key Ctrl+o )&
fi

(пробел перед cd предотвращает переход команды inserted в историю; пробелы после имени каталога необходимы для его работы, но я не знаю, почему.)

еще одна реализация tailcd не использовать xdotool, но это не работает с Midnight Commander:

#!/bin/bash
escapedname=`sed 's/[^a-zA-Z\d._/-]/\\&/g' <<< ""`
perl -e 'ioctl(STDIN, 0x5412, $_) for split "", join " ", @ARGV' " cd" "$escapedname" $'\r'

в идеале, tailcd would/should быть частью bash, использовать обычную межпроцессную связь и т. д.