Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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);

Возможно, это сработает, хотя обратите внимание, что команда Bash pwd кэшируется и не заметит.

Ответ 2

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

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

Ответ 3

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

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

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

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


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

Ответ 4

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

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

Ответ 5

Способ Я решил это, чтобы иметь псевдоним оболочки, вызывающий script и источник файла, который написал script. Так, например,

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

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

cd /some/directory

Это по-прежнему плохое.

Ответ 6

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

alias cdfoo='cd theFooDir'

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

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

Ответ 7

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

Благодаря чрезвычайно полезному обсуждению в https://unix.stackexchange.com/info/213799/can-bash-write-to-its-own-input-stream/...

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

/Бен /mkcd:

mkdir "$1" && tailcd "$1"

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

/Бен /tailcd:

#! /bin/bash
escapedname='sed 's/[^a-zA-Z\d._/-]/\\\\&/g' <<< "$1"'
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 позволяет вставленной команде перейти в историю; для работы требуются пробелы после имени каталога, но я не знаю почему.)

Другая реализация tailcd не использует xdotool, но она не работает с Midnight Commander:

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

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