2013-03-20 2 views
17

В настоящее время bash занимает около 2 секунд для загрузки. Я побежал bash с -x флагом, и я вижу результат, и кажется, что PATH загружается много раз в cygwin. Самое забавное, что я использую один и тот же файл в среде linux, но он отлично работает, без проблемы с перезагрузкой. Может ли следующая проблема возникнуть?Медленное время загрузки bash в cygwin

if [ `uname -o` = "Cygwin" ]; then 
    .... 
fi 
+0

Вы, кажется, задаете две проблемы: у bash есть '--startuptime', и что происходит с этим .bashrc. Вам лучше повезти, задавая каждый вопрос отдельно, и для второго вопроса, объясняя, что конкретно идет не так. –

+0

Я не мог найти опцию '--startuptime' для bash где-нибудь на странице man, а также в Интернете. Я думаю, эти вопросы идут вместе, поэтому я спросил их вместе. – Forethinker

+0

@me_and: Я думаю, вы правы. Я должен был их разделить. Я изменю свой вопрос соответствующим образом. – Forethinker

ответ

21

Как вы уже отметили в своем ответе, проблема заключается в пакете завершения пакета Cygwin. Быстрое и простое исправление состоит в том, чтобы отключить выполнение bash, и правильный способ сделать это - запустить setup.exe Cygwin (download it again, если вам нужно), и выбрать, чтобы удалить этот пакет.

Более длинное решение состоит в том, чтобы работать с файлами в /etc/bash_completion.d и отключать те, которые вам не нужны. В моей системе самые большие виновники замедления времени загрузки Bash (mailman, shadow, dsniff и e2fsprogs) ничего не сделали, поскольку инструменты, которые они были созданы для завершения, не были установлены.

Если вы переименуете файл в /etc/bash_completion.d, чтобы иметь расширение .bak, оно остановит загрузку этого сценария. Таким образом, отключив все, кроме 37 сценариев на одной из моих систем, я сократил среднее время загрузки bash_completion на 95% (от 6,5 секунд до 0,3 секунды).

+1

Кстати, я делал некоторые исследования по этому поводу и [поднял свои выводы и предложения в списке рассылки Cygwin] (http://cygwin.com /ml/cygwin/2013-03/msg00383.html). –

1

Это действительно не проблема, потому что 2 секунды времени загрузки процессора 2-го поколения i7 и SSD на самом деле нормальные. Виновником более длительного времени загрузки, чем родная оболочка linux bash, является /etc/bash_completion, которая входит в состав пакета cygwin. Так что это особая проблема cygwin. Я мог быть совершенно не прав, но из того, что я вижу, каждая программа, установленная через установку, профилируется. Продолжается дискуссия here.

+0

Если у вас есть 2 секунды времени загрузки на обычной машине, у вас есть проблема. Я только принимаю +1 секундное время загрузки на моем старом AMD64 с 2005 года. – oligofren

4

Я знаю, что это старая тема, но после новой установки Cygwin на этой неделе у меня все еще возникает эта проблема.

Вместо того, чтобы копировать все файлы bash_completion, я использовал эту строку для реализации подхода @ me_and для всего, что не установлено на моей машине. Это значительно сократило время запуска bash для меня.

В /etc/bash_completion.d, выполните следующие действия:

for i in $(ls|grep -v /); do type $i >/dev/null 2>&1 || mv $i $i.bak; done 
+1

Это отличный ответ! Для тех, кто думал, что то же, что я сделал (что, конечно, все в этом каталоге анализируется независимо от расширения), получается, что чтение/etc/bash_completion означает, что файлы .bak игнорируются вместе с несколькими другими. Еще одна рекомендация состоит в том, чтобы посмотреть файлы завершения с новым расширением .bak, поскольку некоторые из них относятся к случаям исключений (например, configure, bash-builtins), а некоторые могут быть установлены позднее, поэтому стоит помнить, что вы сделали это в случае, если вы обнаружите, что завершение bash не работает должным образом при установке gcc! – fquinner

14

В моем случае, был контроллер домена Windows. Я сделал это, чтобы найти вопрос:

Я начал с простого, окна cmd.exe и, напечатал это:
c:\cygwin\bin\strace.exe c:\cygwin\bin\bash

В моем случае, я заметил следующую последовательность:

218 12134 [main] bash 11304 transport_layer_pipes::connect: Try to connect to named pipe: \\.\pipe\cygwin-c5e39b7a9d22bafb-lpc 
    45 12179 [main] bash 11304 transport_layer_pipes::connect: Error opening the pipe (2) 
    39 12218 [main] bash 11304 client_request::make_request: cygserver un-available 
1404719 1416937 [main] bash 11304 pwdgrp::fetch_account_from_windows: line: <CENSORED_GROUP_ID_#1> 
    495 1417432 [main] bash 11304 pwdgrp::fetch_account_from_windows: line: <CENSORED_GROUP_ID_#2> 
    380 1417812 [main] bash 11304 pwdgrp::fetch_account_from_windows: line: <CENSORED_GROUP_ID_#3> 

    etc... 

Главное было идентифицировать линию client_request::make_request: cygserver un-available. Вы можете видеть, как после этого cygwin пытается извлечь каждую отдельную группу из окон, а время выполнения сходит с ума.

Быстрый Google показал, что такое cygserver является: https://cygwin.com/cygwin-ug-net/using-cygserver.html

Cygserver это программа, которая предназначена для работы в качестве фона службы.Он предоставляет приложениям Cygwin услуги, для которых требуется арбитраж безопасности или которые необходимо сохранить, пока не запущено ни одно другое приложение cygwin .

Решение было, для запуска cygserver-config, а затем net start cygserver для запуска службы Windows. После этого время запуска Cygwin значительно снизилось.

+0

Я не видел подобного вывода в моей трассе стека, и я не запускаю какой-либо экземпляр cygserver.exe, но спасибо за обмен этой информацией. Не могли бы вы также поделиться версией cygwin, которую используете? – Forethinker

+0

Версия Cygwin '1.7.34 (0.285/5/3) 2015-02-04 12:12 i686' – npe

+0

Это был определенно ответ, который решил мою проблему; Я тоже работал в среде Windows Domain Controller. Спасибо, что поняли. –

2

Мой ответ такой же, как и у npe. Но, поскольку я только что присоединился, я не могу комментировать или даже выдвигать его! Я надеюсь, что этот пост не будет удален, потому что он предлагает заверения для тех, кто ищет ответ на ту же проблему.

Решение npe для меня работало. Есть только одно предостережение - мне пришлось закрыть все процессы cygwin, прежде чем я извлелю максимум из этого. Это включает в себя запуск cygwin-сервисов, таких как sshd, и ssh-agent, который я запускаю из своих сценариев входа. До этого окно для терминала cygwin появлялось мгновенно, но зависало в течение нескольких секунд, прежде чем оно представило приглашение. И он завис в течение нескольких секунд после закрытия окна. После того, как я убил все процессы и запустил службу cygserver (кстати, я предпочитаю использовать Cygwin-путь - cygrunsrv -S cygserver, чем «net start cygserver», я не знаю, имеет ли он какое-либо практическое значение), он начинается немедленно. Так что благодаря npe снова!

3

Новый ответ для старой темы, относящейся к PATH исходного вопроса.

Большинство других ответов касается запуска bash. Если вы видите медленное время загрузки, когда вы запускаете bash -i внутри оболочки, это может применяться.

В моем случае bash -i работал быстро, но в любое время, когда я открывал новую оболочку (будь то в терминале или в xterm), это заняло очень много времени. Если bash -l занимает много времени, это означает, что время входа в систему.

Есть несколько подходов к часто задаваемому вопросу Cygwin: https://cygwin.com/faq/faq.html#faq.using.startup-slow, но они не сработали для меня.

Оригинальный плакат спросил о PATH, который он диагностировал с помощью bash -x. Я тоже обнаружил, что хотя bash -i был быстрым, bash -xl был медленным и показал много информации о PATH.

Существовал такой смехотворно длинный Windows PATH, что процесс входа в систему продолжал запускать программы и искал весь PATH для правильной программы.

Мое решение: отредактируйте Windows PATH, чтобы удалить что-либо лишнее. Я не уверен, какой кусок, который я удалил, сделал трюк, но запуск оболочки для входа шел от 6 секунд до менее 1 секунды.

YMMV.

2

Я нахожусь в корпоративной сети с довольно сложной настройкой, и, похоже, она действительно убивает время запуска cygwin. Относящиеся к ответу NPE, я также должен был следовать некоторые шаги, изложенные здесь: https://cygwin.com/faq/faq.html#faq.using.startup-slow

Еще одной причиной для клиентской системы AD медленно DC ответы, обычно наблюдается в конфигурациях с удаленным доступом постоянного тока. DLL Cygwin запрашивает информацию о каждой группе, в которой вы находитесь, для заполнения локального кеша при запуске. Вы можете немного ускорить этот процесс, кэшируя свою собственную информацию в локальных файлах.Выполнить эти команды в терминале Cygwin с доступом к записи/и т.д.:

getent PASSWD $ (ID) -u>/и т.д./пароль getent группа $ (ID -G)>/и т.д./группы

Кроме установите /etc/nsswitch.conf следующим образом:

ПАРОЛЬ: файлы БД группы: файлы БД

Это ограничит потребность в Cygwin, чтобы связаться с контроллером домена AD (DC) в то же время позволяя для получения дополнительной информации для извлечения из DC, например, при перечислении удаленных каталогов.

После этого, начиная с cygserver, время запуска cygwin значительно снизилось.

0

Как упоминалось выше, одна из возможных проблем заключается в том, что переменная среды PATH содержит слишком большой путь, cygwin будет искать все из них. Я предпочитаю прямое редактирование/etc/profile, просто переписываю переменную PATH в связанный с cygwin путь, например. PATH="/usr/local/bin:/usr/bin". Добавьте дополнительный путь, если хотите.

0

Я написал функцию Bash с именем «minimizecompletion» для инактивации не необходимых скриптов завершения.

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

Мое решение состоит в том, чтобы удалить все загруженные спецификации завершения, загрузить сценарий завершения и проверить, добавили ли они новые спецификации завершения. В зависимости от этого он инактивируется путем добавления .bak к имени файла сценария или активируется путем удаления .bak. Выполнение этого для всех 182 скриптов в файле /etc/bash_completion.d приводит к 36 активным и 146 неактивным сценариям завершения, сокращая время запуска Bash на 50% (но должно быть ясно, что это зависит от установленных пакетов).

Функция также проверяет инактивированные скрипты завершения, чтобы активировать их, когда они необходимы для новых установленных пакетов Cygwin. Все изменения могут быть отменены с помощью аргумента -a, который активирует все сценарии.

# Enable or disable global completion scripts for speeding up Bash start. 
# 
# Script files in directory '/etc/bash_completion.d' are inactived 
# by adding the suffix '.bak' to the file name; they are activated by 
# removing the suffix '.bak'. After processing all completion scripts 
# are reloaded by calling '/etc/bash_completion' 
# 
# usage: [-a] 
#   -a activate all completion scripts 
# output: statistic about total number of completion scripts, number of 
#   activated, and number of inactivated completion scripts; the 
#   statistic for active and inactive completion scripts can be 
#   wrong when 'mv' errors occure 
# return: 0 all scripts are checked and completion loading was 
#    successful; this does not mean that every call of 'mv' 
#    for adding or removing the suffix was successful 
#   66 the completion directory or loading script is missing 
# 
minimizecompletion() { 
    local arg_activate_all=${1-} 
    local completion_load=/etc/bash_completion 
    local completion_dir=/etc/bash_completion.d 

    (
    # Needed for executing completion scripts. 
    # 
    local UNAME='Cygwin' 
    local USERLAND='Cygwin' 
    shopt -s extglob progcomp 
    have() { 
     unset -v have 
     local PATH="$PATH:/sbin:/usr/sbin:/usr/local/sbin" 
     type -- "$1" &>/dev/null && have='yes' 
    } 

    # Print initial statistic. 
    # 
    printf 'Completion scripts status:\n' 
    printf ' total:  0\n' 
    printf ' active:  0\n' 
    printf ' inactive: 0\n' 
    printf 'Completion scripts changed:\n' 
    printf ' activated: 0\n' 
    printf ' inactivated: 0\n' 

    # Test the effect of execution for every completion script by 
    # checking the number of completion specifications after execution. 
    # The completion scripts are renamed depending on the result to 
    # activate or inactivate them. 
    # 
    local completions total=0 active=0 inactive=0 activated=0 inactivated=0 
    while IFS= read -r -d '' f; do 
     ((++total)) 
     if [[ $arg_activate_all == -a ]]; then 
     [[ $f == *.bak ]] && mv -- "$f" "${f%.bak}" && ((++activated)) 
     ((++active)) 
     else 
     complete -r 
     source -- "$f" 
     completions=$(complete | wc -l) 
     if (($completions > 0)); then 
      [[ $f == *.bak ]] && mv -- "$f" "${f%.bak}" && ((++activated)) 
      ((++active)) 
     else 
      [[ $f != *.bak ]] && mv -- "$f" "$f.bak" && ((++inactivated)) 
      ((++inactive)) 
     fi 
     fi 
     # Update statistic. 
     # 
     printf '\r\e[6A\e[15C%s' "$total" 
     printf '\r\e[1B\e[15C%s' "$active" 
     printf '\r\e[1B\e[15C%s' "$inactive" 
     printf '\r\e[2B\e[15C%s' "$activated" 
     printf '\r\e[1B\e[15C%s' "$inactivated" 
     printf '\r\e[1B' 
    done < <(find "$completion_dir" -maxdepth 1 -type f -print0) 

    if [[ $arg_activate_all != -a ]]; then 
     printf '\nYou can activate all scripts with %s.\n' "'$FUNCNAME -a'" 
    fi 
    if ! [[ -f $completion_load && -r $completion_load ]]; then 
     printf 'Cannot reload completions, missing %s.\n' \ 
      "'$completion_load'" >&2 
     return 66 
    fi 
) 

    complete -r 
    source -- "$completion_load" 
} 

Это пример вывода и результирующие раз:

$ minimizecompletion -a 
Completion scripts status: 
    total:  182 
    active:  182 
    inactive: 0 
Completion scripts changed: 
    activated: 146 
    inactivated: 0 

$ time bash -lic exit 
logout 

real 0m0.798s 
user 0m0.263s 
sys  0m0.341s 

$ time minimizecompletion 
Completion scripts status: 
    total:  182 
    active:  36 
    inactive: 146 
Completion scripts changed: 
    activated: 0 
    inactivated: 146 

You can activate all scripts with 'minimizecompletion -a'. 

real 0m17.101s 
user 0m1.841s 
sys  0m6.260s 

$ time bash -lic exit 
logout 

real 0m0.422s 
user 0m0.092s 
sys  0m0.154s 
3

Все ответы относятся к более старым версиям bash_completion, и не имеют никакого отношения к недавним bash_completion.

Современные bash_completion переехал большинство файлов заканчивания к /usr/share/bash-completion/completions по умолчанию, проверьте путь на вашей системе, запустив

# pkg-config --variable=completionsdir bash-completion 
/usr/share/bash-completion/completions 

Есть много файлов там, по одному для каждой команды, но это не проблема , так как они загружаются по требованию при первом использовании с каждой командой. Старый /etc/bash_completion.d по-прежнему поддерживается для совместимости, и все файлы оттуда загружаются при запуске bash_completion.

# pkg-config --variable=compatdir bash-completion 
/etc/bash_completion.d 

Используйте этот скрипт, чтобы проверить, остались ли в старой директории устаревшие файлы.

#!/bin/sh 
COMPLETIONS_DIR="$(pkg-config --variable=completionsdir bash-completion)" 
COMPAT_DIR="$(pkg-config --variable=compatdir bash-completion)" 
for file in "${COMPLETIONS_DIR}"/*; do 
    file="${COMPAT_DIR}/${file#${COMPLETIONS_DIR}/}" 
    [ -f "$file" ] && printf '%s\n' $file 
done 

Он выводит список файлов в директории Compat, которые также присутствуют в новее (по требованию) доработок реж. Если у вас нет конкретных причин, чтобы сохранить некоторые из них, просмотрите, создайте резервную копию и удалите все эти файлы.

В результате совместимый каталог должен быть в основном пустым.

Теперь, для самой интересной части - проверка, почему bash запуск медленный. Если вы только запустили bash, он запустит не-логин, интерактивный shell - этот на источнике Cygwin /etc/bash.bashrc, а затем ~/.bashrc. Это, скорее всего, не включает завершение bash, если вы не используете его из одного из rc-файлов. Если вы запустите bash -l (bash --login), начните Cygwin Terminal (зависит от cygwin.bat), или войти в систему с помощью SSH, он начнет входа в систему, интерактивную оболочку - которая будет источником /etc/profile, ~/.bash_profile, и вышеупомянутые радиоуправляемые файлы. Сам сценарий /etc/profile выводит все исполняемые файлы .sh в /etc/profile.d.

Вы можете проверить, как долго каждый файл переходит в исходный код. Найти этот код в /etc/profile:

for file in /etc/profile.d/*.$1; do 
    [ -e "${file}" ] && . "${file}" 
done 

Назад его, а затем заменить его следующим образом:

for file in /etc/profile.d/*.$1; do 
    TIMEFORMAT="%3lR ${file}" 
    [ -e "${file}" ] && time . "${file}" 
done 

bash Start, и вы увидите, как долго каждый файл взял. Исследуйте файлы, которые занимают значительное количество времени. В моем случае это были bash_completion.sh и fzf.sh (fzf - нечеткий искатель, действительно приятное дополнение к bash_completion). Теперь выбор состоит в том, чтобы отключить его или продолжить исследование. Поскольку я хотел продолжать использовать fzf ярлыки в bash, я исследовал, нашел источник замедления, оптимизировал его и отправил свой патч в репозиторий fzf (надеюсь, он будет принят).

Настоящее имя для самого большого времени spender - bash_completion.sh. В основном это источники сценариев /usr/share/bash-completion/bash_completion. Я сделал резервную копию этого файла, а затем отредактировал его. На последней странице есть for цикл, который отправляет все файлы в compat dir - /etc/bash_completion.d. Опять же, я добавил TIMEFORMAT и time и увидел, какой сценарий вызывает медленный запуск. Это было zzz-fzf (fzf). Я исследовал и нашел подоболочку ($()), выполняемую несколько раз в цикле for, переписал эту часть без использования подоболочки, что ускоряет работу скрипта. Я уже отправил свой патч в репозиторий fzf.

Самая большая причина для всех этих замеров: fork не поддерживается технологией Windows, Cygwin отлично справляется с этим, но это очень медленно, по сравнению с реальной UNIX. Подселл или конвейер, который очень мало работает сам, тратит большую часть времени выполнения на fork -ing. Например. сравните время выполнения time echo msg (0.000s на моем Cygwin) против time echo $(echo msg) (0.042s на моем Cygwin) - день и ночь. Команда echo сама по себе не делает сколько-нибудь заметного времени для выполнения, но создание подоболочки очень дорого. В моей системе Linux эти команды занимают соответственно 0,000 и 0,001. Многие пакеты Cygwin разрабатываются людьми, которые используют Linux или другую UNIX, и могут работать на Cygwin без изменений.Поэтому, естественно, эти разработчики могут свободно использовать подоболочки, конвейеры и другие функции везде, где это удобно, так как они не ощущают существенной производительности в своей системе, но на Cygwin эти сценарии оболочки могут работать в десятки и сотни раз медленнее.

Нижняя строка, если скрипт оболочки работает медленно в Cygwin - попробуйте найти источник fork звонков и переписать сценарий, чтобы устранить их как можно больше. . cmd="$(printf "$1" "$2")" (использует одну вилку для подоболочки) можно заменить на printf -v cmd "$1" "$2".

Мальчик, он вышел очень долго. Любые люди, которые до сих пор читают здесь, являются настоящими героями. Спасибо :)

+0

Еще чтение! Получаю ли я значок? : D – cxw

Смежные вопросы