функция псевдонима или удара не работает

Страницы справочника являются обычно краткими справочными документами. Википедия является лучшим местом для превращения к для концептуальных объяснений.

Ветвление копирует процесс: это создает дочерний процесс, который почти идентичен родительскому процессу (наиболее заметное отличие - то, что новый процесс имеет другой идентификатор процесса). В частности, ветвление (концептуально) должно скопировать память всего родительского процесса.

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

if (fork()) {
    # parent process …
} else {
    # child process (with a new copy of the process memory)
    execve("/bin/sh", …);  # discard the process memory
}

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

Таким образом vfork вызов был изобретен. Это не делает копию памяти. Поэтому vfork является дешевым, но трудно использовать, так как необходимо удостовериться, что Вы не получаете доступ ни к одному стековому пространству процесса или пространству "кучи" в дочернем процессе. Обратите внимание, что даже чтение могло быть проблемой, потому что родительский процесс продолжает выполняться. Например, этот код взломан (он может или не может работать в зависимости от того, получают ли ребенок или родитель интервал времени сначала):

if (vfork()) {
    # parent process
    cmd = NULL; # modify the only copy of cmd
} else {
    # child process
    execve("/bin/sh", "sh", "-c", cmd, (char*)NULL);  # read the only copy of cmd
}

Начиная с изобретения vfork была изобретена лучшая оптимизация. Большинство современных систем, включая Linux, использует форму копии на записи, где страницы в памяти процесса не копируются во время fork звоните, но позже когда родитель или ребенок сначала запишут в страницу. Таким образом, каждая страница начинается, как совместно использовано и остается общей, пока любой процесс не пишет в ту страницу; процесс, который записи получают новую физическую страницу (с тем же виртуальным адресом). Копия на записи делает vfork главным образом бесполезный с тех пор fork не сделает копии в случаях где vfork было бы применимо.

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

3
18.03.2011, 20:23
3 ответа

Почему псевдоним не работает

alias wd='ps -ef | grep java | awk {'print $2 " " $9'} | egrep "(A|B|C|D)"'

alias команда получает три аргумента. Первой является строка wd=ps -ef | grep java | awk {print (одинарные кавычки предотвращают символы между ними от наличия особого значения). Второй аргумент состоит из символа одиночного пробела. (В .bashrc, позиционные параметры $2 и $9 пусты, таким образом, $2 расширяется до списка 0 слов.) Третий аргумент } | egrep "(A|B|C|D)" (снова одинарные кавычки защищают специальные символы).

Определение псевдонима анализируется как любая другая команда оболочки, когда с этим встречаются. Затем строка, определенная для псевдонима, анализируется, когда псевдоним расширен. Вот некоторые возможные способы определить этот псевдоним. Первая возможность: так как целое определение псевдонима в одинарных кавычках, только используйте двойные кавычки в командах, что означает, что необходимо защитить " и $ предназначенный для awk с обратными косыми чертами.

alias wd='ps -ef | grep java | awk "{print \$2 \" \" \$9}" | egrep "(A|B|C|D)"'

Вторая возможность: каждый символ обозначает себя в одинарных кавычках, за исключением того, что одинарная кавычка заканчивает литеральную строку. '\'' идиома для “одинарной кавычки в единственно заключенной в кавычки строке”: закончите единственно заключенную в кавычки строку, поместите литеральную одинарную кавычку и сразу запустите новую единственно заключенную в кавычки строку. С тех пор нет никакого прошедшего пространства, это - все еще то же слово.

alias wd='ps -ef | grep java | awk '\''{print $2 " " $9}'\'' | egrep "(A|B|C|D)"'

Можно упростить это немного:

alias wd='ps -ef | grep java | awk '\''{print $2, $9}'\'' | egrep "(A|B|C|D)"'

Подсказка: использовать set -x видеть, как оболочка разворачивает Ваши команды.

Почему функция не работает

Я не знаю. Часть Вы показываете взгляды хорошо. Если Вы все еще не понимаете, почему Ваша функция не работает после моих объяснений, вставки копии Ваш код.

Псевдоним или функция?

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

alias grep='grep --color'
alias cp='cp -i'
alias j=jobs

Для чего-либо более сложного используйте функции.

Что необходимо было записать

Вместо того, чтобы анализировать ps вывод, заставьте его генерировать вывод, который подходит Вам.

wd () {
  ps -C java -o pid=,cmd= | egrep "(A|B|C|D)"
}
6
27.01.2020, 21:11

Проблема с псевдонимом состоит в том, что кавычки не вкладывают непосредственно (кроме, как особый случай, внутри $()). Необходимо выйти из внутренних.

alias wd='ps -ef | grep java | awk {\'print $2 " " $9\'} | egrep "(A|B|C|D)"'
#                                   ^^               ^^

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

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

2
27.01.2020, 21:11
  • 1
    Несколько ошибок здесь. Ваше заключение в кавычки не работает вообще: обратные косые черты не являются специальными внутренними одинарными кавычками. (См. мой ответ при необходимости в большем количестве объяснения.) Псевдоним, заканчивающийся пространством, не имеет никакого влияния на завершение в ударе (я думаю). Псевдонимы действительно работают, как только они объявляются (или в ударе, возможно, только на следующей строке, но это - ошибка); циклы расширения псевдонима предотвращены совершенно другим механизмом (псевдоним foo не расширен в (прямой или косвенный) результат расширения foo). –  Gilles 'SO- stop being evil' 18.03.2011, 21:20

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

alias wd='ps -ef | grep java | awk {'print $2 " " $9'} | egrep "(A|B|C|D)"'

приведет к команде wd arg1 arg2 arg3 будучи замененным и выполняемый как

ps -ef | grep java | awk {'print " " '} | egrep "(A|B|C|D)" arg1 arg2 arg3

Для всего кроме того, используйте функции.

0
27.01.2020, 21:11
  • 1
    На самом деле, потому что $2 и $9 внутренние одинарные кавычки, они не будут расширены оболочкой, но awk, который использует их в качестве полевых селекторов для ps вывод: uid и первый аргумент команде, для Linux ps -f. Тем не менее неудавшееся вложенное заключение в кавычки означает, что оболочка разворачивала их, когда это не должно было быть. –  geekosaur 18.03.2011, 20:53
  • 2
    @geekosaur, о, да, конечно. Я не посмотрел на него тот путь. –  artistoex 18.03.2011, 20:58
  • 3
    @geekosaur, @artistoex: Да, можно передать аргумент псевдониму, и на самом деле это является наиболее часто используемым. Здесь, $2 и $9 незащищены, когда псевдоним определяется. См. мой ответ для полной истории. –  Gilles 'SO- stop being evil' 18.03.2011, 21:22
  • 4
    @gilles аргумент не передается псевдониму в смысле, который Вы не можете произвести, куда исходные аргументы будут помещены в заключительную командную строку. Это будет всегда помещаться в конец. –  artistoex 19.03.2011, 12:30

Теги

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