Что такое переменные среды Windows

Операционные системы и Windows не исключение имеют в своем составе особый механизм хранения различной информации, называемый переменными. Кто знаком с программированием прекрасно понимает, что это. Остальные могут представить себе это в виде записи имя_переменной=значение переменной среды. Например, запись username=Vasya означает, что переменная с именем username содержит значение Vasya.
При этом подразумевается, что имя переменной неизменно, а значение может изменяться с течением времени. Представим себе, что в переменной username хранится имя текущего пользователя Windows. Когда мы вошли в систему под именем Vasya, то в username оказалось соответствующее значение, однако если мы сменим пользователя на Ivan, то и значение изменится и username будет равно Ivan. Из-за этой возможности изменяться их и называют переменными.
Они оказываются чрезвычайно полезными при создании скриптов, работе в командной строке и адресной строке Проводника. В основном они содержат информацию из разряда имя компьютера, имя пользователя, домашняя папка пользователя, каталог куда установлена ОС, архитектура процессора, папки для временных файлов и так далее.
Таким образом эта информация дает представление о текущем окружении, то есть описывает среду, в которой происходит выполнение программы, отсюда и получили свое название переменные среды (environment variables) или по-другому переменные окружения.
В чем их практический смысл? Представьте себе, что вы создаете командный файл, в котором используется путь к домашней папке пользователя, причем он должен работать на любом компьютере. Как его прописать, если имя учетной записи заранее не известно, да и расположение папки тоже? Конечно, его можно выяснить в недрах ОС, но гораздо проще и компактней просто написать %USERPROFILE%. Система сама заботится о правильном значении, поэтому в таком варианте скрипт будет корректно работать везде.
Вот другой пример. Если в адресную строку Проводника ввести %localappdata% и нажать Enter , то произойдет переход в папку, которую установленные программы используют для хранения своих локальных данных. Обычно это C:\Users\имя текущей учетной записи\AppData\Local в которую можно конечно перейти обычным способом, но учитывая, что AppData является скрытой, то данный способ может оказаться быстрее и проще. К тому же можно создавать собственные переменные среды на нужные папки.
Так же благодаря переменной path можно запускать программы без указания полных путей к исполняем файлам, что заметно упрощает использование компьютера.
Переменные среды Windows бывают нескольких видов:
- Системные переменные — работают в пределах всего компьютера, хранятся в реестре в разделе HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
- Пользовательские переменные — действуют только для конкретной учетной записи и находятся в реестре по адресу HKCU\Environment
- Сессионные переменные — существуют только в пределах текущего сеанса окна командной строки.
Настройка переменных среды Windows
В операционной системе имеется заранее предопределенный набор переменных окружения Windows и можно создавать собственные. Для просмотра и управления ими можно воспользоваться графическим интерфейсом. В разных версиях Windows вид окон немного отличается, но принципиально все одинаково. Правда в Windows 10 управление реализовано более удобно, чем в 7 и более старых версиях.
Настройка переменных среды Windows в графическом интерфейсе
Чтобы иметь возможность просматривать и редактировать переменные окружения в Windows 10 нужно выполнить следующие действия.
Щелкнуть правой кнопкой мыши по иконке «Этот компьютер» на рабочем столе и выбрать в меню «Свойства» или набрать в поиске на панели задач «Панель управления». Затем в левом столбце нажать на «Дополнительные параметры системы». В новом окне на вкладке «Дополнительно» есть кнопка «Переменные среды». Альтернативный вариант нажать комбинацию клавиш WIN + R и ввести systempropertiesadvanced .

Окно управления состоит из двух частей. В верхней представлены пользовательские переменные, а в нижней системные. Здесь можно просмотреть существующие, а также отредактировать, удалить или создать новые воспользовавшись соответствующими кнопками.

Чтобы создать переменную окружения нажимаем кнопку «Создать» в нужной части окна и вводим ее имя, значение и затем OK. Можно воспользоваться кнопкой «Обзор каталога» чтобы не вводить путь до нужной папки вручную.
Настройка переменных окружения Windows в командной строке
Конечно, есть альтернативный вариант настройки переменных окружения с помощью командной строки Windows. Чтобы cmd правильно понял, о чем идет речь ее нужно обернуть в символы процента вот так, %имя_переменной%. Соответственно, чтобы вывести на экран значение переменной среды команда будет такой: echo %имя_переменной% .
В Windows есть специальные команды, предназначенные для создания и редактирования переменных. Это set и setx принципиальная разница между которыми в том, что первая управляет ими только в текущем окне командной строки, а вторая изменяет их «навсегда» поскольку изменения сохраняются в реестре.
Для просмотра всех существующих переменных и их значений введите set без параметров.

Тут есть важный момент, который нужно понять, переменные среды считываются в момент запуска программы. Поэтому изменения, сделанные в графическом интерфейсе или командой setx не действуют на уже запущенные программы. Их придется закрыть и запустить снова. В то же время команда set влияет только на текущее окно или дочерние процессы.
Чтобы создать пользовательскую переменную среды или отредактировать существующую общий вид команды следующий setx имя значение , использовать кавычки при наличии пробелов. Если переменной с таким именем не существует, то она будет создана, в противном случае значение будет изменено на новое. Для управления системными переменными нужно дополнить команду ключом /m и командная строка должна быть запущена с правами администратора компьютера setx mypc T-800 /m .

Впрочем, у setx имеется недостаток, с ее помощью нельзя удалить существующую переменную, максимум можно присвоить ей пустое значение setx mypc «» . Хотя при этом она как бы не существует для cmd, но фактически она продолжает оставаться в реестре. Полноценное удаление возможно непосредственно в реестре или с помощью команд, обеспечивающих работу с ним, а также в графическом интерфейсе.
Для работы с сеансовыми переменными используется команда set. Синтаксис несколько отличается set имя=значение . Здесь уже используется знак равенства вместо пробела, при этом не допускается его наличие в имени. Таким образом изменить переменную окружения с именем temp в текущем окне CMD можно командой: set temp=D:\Archive\Garbage .

Использование переменных среды Windows сильно упрощает и ускоряет использование компьютера опытными пользователями. Каким способом их использовать каждый решает самостоятельно.
Поделиться понравившейся статьей:
Утилита GBAK, Firebird и InterBase
Утилита gbak, входящая в комплект любого дистрибутива СУБД Firebird и InterBase, является средством создания резервных копий баз данных и восстановления баз данных из резервных копий.
Термин «резервное копирование» имеет достаточно общий смысл, целью которого является получение копии базы данных, пригодной для архивирования. Например, «резервную копию» БД можно изготовить простым способом – скопировать базу данных, предварительно остановив Firebird/InterBase (иначе, при работающем сервере, копия будет являться «поврежденным файлом», т. к. копирование производится последовательно, а база данных – файл произвольного доступа). Если же нужно сделать резервную копию базы данных «на ходу», во время работы СУБД, то для этого и предназначен gbak.
Далее в статье будет рассматриваться только использование утилиты командной строки, т. к. она есть во всех дистрибутивах для всех платформ, и в отличие от интерактивных средств, использующих Services API (например, IBExpert), позволяет автоматизировать процесс резервного копирования.
Создание резервных копий – backup
gbak является программой, которая подсоединяется к базе данных, стартует транзакцию snapshot, и затем сохраняет в специальный файл метаданные (описания таблиц, процедур, триггеров и т. д.) и данные (запросами select * from tablename). Вы можете самостоятельно написать подобную программу, например, для экспорта данных из БД в какой-либо другой формат.
Благодаря тому, что считывание данных происходит в транзакции snapshot, gbak на протяжении процесса чтения данных «видит» неизменные данные благодаря версионности. То есть, во время работы gbak другие приложения могут работать с базой данных. Однако, те изменения, которые были произведены приложениями во время работы gbak, разумеется не будут сохранены в резервную копию БД.
Формат командной строки для создания резервной копии простой:
Основная опция при создании резервной копии -b (другие опции подробно описаны дальше). Причем опции могут быть указаны как в начале, так и в конце. Как правило, gbak при выполнении резервного копирования и восстановления требует указать имя и пароль пользователя. Это могут быть или SYSDBA, или имя владельца базы. Например:
gbak -b employee.fdb emp.fbk -user SYSDBA -pass masterke
Чтобы не засорять текст постоянными -user. -pass. я дальше в примерах не буду приводить их в командной строке. Если же вы предполагаете вызывать gbak несколько раз подряд в одном окне консоли или bat/cmd-файле, то можно установить переменные среды
SET ISC_USER=SYSDBA
SET ISC_PASSWORD=masterke
после чего в этом окне консоли или bat/cmd файле вводить опции -user и -password не потребуется.
Также для облегчения читаемости я рекомендую использовать следующий «формат» командной строки:
gbak -b [другие опции] [-v -y ] -user . -pass .
То есть, «что делаем», «с какими параметрами», «база и копия», «полный вывод лога», «пользователь и пароль». Такой порядок в левой части, где концентрируется внимание, содержит ключевую информацию, а правая часть – содержит вторичную информацию. Разумеется, вы можете выбрать иной порядок следования параметров gbak, но далее в статье я буду придерживаться указанного порядка.
Если вы хотите потренироваться по мере чтения статьи, то я рекомендую вам взять employee.fdb (или employee.gdb) из папки установки Firebird (InterBase), и скопировать эту базу в каталог bin, рядом с gbak. Затем открыть окно консоли, и перейти в каталог bin. Предварительно, чтобы не мучиться со вводом, рекомендую employee.fdb переименовать в e.fdb.
Итак, выполняем командную строку:
gbak -b e.fdb e.fbk
Что-то произошло, т. к. на диске образовался e.fbk, но никаких сообщений выдано не было. gbak в таком режиме выводит только сообщения об ошибках, если таковые возникли. Впрочем, для систем с регулярным резервным копированием, а также когда backup выполняется долго, лучше сразу указать опцию полного вывода лога действий. Даже в случае появления ошибки контекст этой ошибки будет виден четче, и также будет видно что именно сервер успел поместить в резервную копию до ошибки. Повторяем команду с ключом -v:
gbak -b e.fdb e.fbk -v
Теперь видно, что делает gbak при -b. Правда, по умолчанию размер буфера консоли небольшой, и вы увидите только финальную часть лога. Чтобы лог можно было посмотреть полностью, придется еще раз повторить команду, только теперь уже с перенаправлением лога в файл:
gbak -b e.fdb e.fbk -v -y e_bak.txt
Теперь опять на экран ничего не выводится, зато можно посмотреть e_bak.txt и изучить его. Предоставляю вам сделать это самостоятельно. Кстати, если вы попытаетесь еще раз повторить такую же командную строку, то gbak выдаст ошибку.
Внимание! gbak при создании резервной копии уничтожит файл с таким же именем. Однако для ключа -y при указании вывода файла лога этот файл не перезаписывается.
Замечание. Параметр -v в справке, выдаваемой gbak, описан как -v[erify]. Это неверно, потому что опция gbak -v не имеет ничего общего с проверкой БД. Скорее, этот параметр должен расшифровываться как «verbose».
Имена файлов
Немного отвлечемся, и рассмотрим, что и как мы можем указывать в качестве имени базы данных и имени резервной копии.
Имя базы
Поскольку уже было сказано, что gbak это обычная программа, которая читает данные из БД, то сама база данных и сервер могут находиться где угодно. В примерах выше использован локальный коннект, подразумевающий, что gbak выполняется на сервере. Если бы мы запускали gbak с клиентской машины, и обращались к серверу, то тогда вместо
надо было бы писать
server:c:\Firebird\bin\e.fdb
то есть штатную строку коннекта с указанием сервера и пути к БД (или алиаса, если таковой сконфигурирован в aliases.conf для Firebird 1.5 и выше, или admin.ib для InterBase 7.x и выше). В нашем примере вместо server надо указать или имя вашего компьютера, или localhost, поскольку мы все делаем на одном компьютере.
Разумеется, gbak создавая резервную копию, будет создавать ее локально, т. е. на компьютере где находится gbak. И если сервер – это другой компьютер, то фактически вся база данных будет считана по сети. Не стоит делать резервные копии баз размером гигабайт и выше например через 100мбит сеть. Быстрее будет сделать резервную копию на сервере, а затем просто скопировать ее файл на другой компьютер (если это нужно).
Имя резервной копии
Абсолютно любое, включая любое расширение. Вы можете встретить bak, gbk, fbk, и так далее. Никаких ограничений в этом плане не накладывается. Имя резервной копии лучше формировать как имя базы и дату, причем дату лучше всего указывать в «японском» формате, в виде YYYYMMDD – так имена файлов будут корректно сортироваться при просмотре папки.
Существует возможность делать многофайловый бэкап, разбивая бэкап на части. Однако, такая функциональность была нужна когда были распространены файловые системы, не поддерживавшие файлы более 2-4 гигабайт, а также когда InterBase не поддерживал как базы так и бэкапы более 4-х гигабайт. В настоящее время нет никакого смысла создавать как многофайловые бэкапы, так и многофайловые базы данных, поэтому данная функциональность в этой статье не описана.
Имя файла лога
То же самое, что и для резервной копии, включая расширение. Расширение лога имеет смысл выбрать таким, чтобы по умолчанию файл открывался Блокнотом или программой, которой вы привыкли просматривать текстовые файлы. Если же задать расширение как .log, а ассоция с ним не назначена, то при попытке просмотра вы каждый раз будете мучиться выбирая подходящую программу в выдаваемом Windows списке.
Дополнительные параметры backup
Вот перечень опций командной строки gbak, которые используются при создании резервных копий БД (в квадратных скобках указаны символы, которые можно не указывать в командной строке):
| Опция | Назначение |
|---|---|
| -b[ackup_database] | создать резервную копию |
| -g[arbage_collect] | отключить сборку мусора |
| -co[nvert] | конвертировать external table во внутренние таблицы БД |
| -ig[nore] | при работе с поврежденной БД |
| -L[imbo] | игнорировать изменения «застрявших» транзакций 2PC (указана прописная буква L, потому что в большинстве шрифтов на экране строчная буква l похожа на 1. Вы можете использовать строчный вариант) |
| -m[etadata] | сохранить только метаданные (без данных) |
| -t[ransportable] | для переноса БД между разными аппаратными платформами (по умолчанию) |
| -nt | формат резервной копии, непереносимой между аппаратными платформами |
| -v | вывод полного лога процесса backup |
| -y | сохранить вывод лога в файл |
| -user | имя пользователя, SYSDBA или владелец БД |
| -pas[sword] | пароль SYSDBA или владельца БД. Опция может быть сокращена до -pass |
| -e[xpand] | отключение сжатия данных при backup. По умолчанию резервная копия записывается в «сжатом» виде. |
| -ol[d_descriptions] | для совместимости с InterBase 3.3. Атавизм |
| -fa[ctor] n | для ленточных устройств. Атавизм |
| -z | вывод версии сервера и gbak |
| Новая опция Firebird 2.1 | |
| -nodbtriggers | отключает срабатывание триггеров уровня базы данных. Эту опцию может указать только SYSDBA или владелец БД |
| -tru | включает использование trusted authentification (для всех утилит) |
| Новая опция Firebird 2.5.5 | |
| -st TDRW | Вывод статистики при выполнении различных операций: T — время с момента старта, D — время выполнения операции, R — чтений страниц, W — записи страниц. Бэкпортировано из Firebird 3.0 |
| Новая опция InterBase 2007 | |
| -d | создать online dump (инкрементный бэкап). Подробнее см. Update Guide |
| Новые опции InterBase 2009 | |
| -encrypt | шифровать базу с существующим в базе ключом шифрования. Подробнее читайте Data Definition Guide, раздел Encrypting backup files. |
| -sep | указание System Encryption Password |
| Новые опции Firebird 3.0 | |
| -skip_d table1|table2|. | Не сохранять в бэкап данные указанных таблиц. Таблицы в списке разделяются символом | |
| -st TDRW | Вывод статистики во время выполнения gbak: T — время с начала, D — разница, R — чтений страниц, W — записи страниц |
| -veribi | вывод через n записей таблиц |
Подробное описание каждого параметра:
-g
Самый важный параметр. Часто встречается его описание как «отключает сборку мусора», но если подробнее, то этот параметр запрещает серверу проверять читаемые записи на наличие мусорных, что ускоряет процесс бэкапа. Более подробно это описано в документе. Здесь я только подчеркну, что создание резервной копии должно выполняться максимально быстро, а соответственно лучше не загружать сервер в это время сборкой мусора. Поэтому рекомендую всегда использовать такое начало командной строки бэкапа
Если вы делаете бэкап в IBExpert, то включение опции -g производится отключением (!) галки на параметре Garbage collection (или Включить сборку мусора). Почему так сделано – не очень понятно, но такое «обратное» поведение присутствует во многих инструментах, аналогичных IBExpert-у. Возможно так случилось потому, что сам параметр командной строки называется -garbage_collect, в то же время он наоборот, не включает, а отключает сборку мусора в коннекте gbak.
Примечание. Разумеется, при backup никакой «мусор» никогда не попадает в файл backup, ни при каких условиях. Если это не очевидно, то прочитайте еще раз, что делает утилита gbak при backup. Если и там вы не увидели объяснения, то это значит, что вы не понимаете как сервер работает с транзакциями.
-t
Этот параметр можно часто увидеть в командных строках бэкапа, приводимых или цитируемых на различных форумах. На самом деле этот параметр действует по умолчанию, поэтому указывать его нет никакой необходимости.
transportable в данном случае означает, что полученный файл резервной копии можно восстановить на альтернативной аппаратной платформе, где порядок байт в целых числах отличается. То есть, например, между Intel и Sparc, или HP-UX и Intel, и так далее. Но между Windows и Linux (или другой ОС) на Intel файл резервной копии будет и так переносимым, даже при указании ключа -nt (non-transportable). Так что, про -t, как и про -nt можно забыть, и никогда не указывать их в командной строке gbak.
-e
InterBase был создан примерно в 1985-86 годах, а тогда жесткие диски были очень малого объема. Поэтому по умолчанию gbak -b производит некую легкую компрессию данных. Отключить ее можно параметром -expand. Я сделал тест бэкапа базы 2.6 гигабайт, и обнаружил, что вместо обычного 2.2 гигабайта (база только что после restore, поэтому разница между размером БД и бэкапом невелика, обычно она больше) файл резервной копии с параметром -expand стал 5.2 гигабайта. Провел еще тесты, с резервным копированием на другой диск. Получил ускорение с -expand на 5%. Визуально процессор загружен на те же самые 34-38%, что и без ключа -e. На restore, скорее всего, разницы вообще не будет заметно. Так что практическую полезность параметра -expand, учитывая сильное увеличение размера резервной копии, можно считать равной нулю.
Другой тест, более поздний, на базе размером 30 гигабайт. Бэкап с -e быстрее на 7.5%, но размер бэкапа на 10% больше размера исходной БД, и на 30% больше бэкапа без опции -e.
Если база еще больше, и ее бэкап идет 10 часов, то опция -e даст ускорение на 7.5%, это 45 минут. Но будет проигрыш в размере бэкапа. Так что, вывод о бесполезности -e остается прежним.
-co
Если в базе данных созданы внешние таблицы (external tables), то при создании резервной копии они будут помещены внутрь бэкапа как обычные таблицы. Без параметра -co внешние таблицы в резервную копию не попадают.
Можно сказать, что -co нужен тогда, когда вам требуется для эксперимента «взять с собой» не только базу, но и внешние файлы. Правда, в зависимости от назначения эти файлы могут иметь разный размер, и может оказаться, что сами они будут больше чем база данных. Для обычного, регулярного backup, параметр -co не нужен.
-factor
В документации этот параметр указан как «uses blocking factor n for tape device». Что это такое – уже неизвестно, т. к. в документации по нынешним версиям InterBase описания этого параметра нет, да и на ленту уже мало кто делает резервные копии (разве что копии дисков целиком).
-ig
До InterBase 5 сервер использовал вычисление контрольных сумм страниц БД. С InterBase 5 эта функциональность была отключена, поскольку диски сами научились восстанавливать поврежденные блоки по контрольным суммам, и поврежденный блок либо восстанавливается автоматически и незаметно, либо не может быть восстановлен вообще.
Сейчас InterBase и Firebird вместо контрольной суммы записывают на страницу число «12345». Если произошло повреждение базы данных, и данные на страницах БД искажены (нули или другая произвольная информация), то сервер при чтении такой страницы будет выдавать ошибку контрольной суммы.
Параметр -ig позволяет игнорировать ошибки контрольных сумм страниц, и не останавливать резервное копирование из-за этих ошибок.
Поэтому, в обычной командной строке для создания резервной копии БД категорически не рекомендуется указывать параметр -ig! Если база данных вдруг окажется повреждена, то с этим параметром вы можете «не увидеть» повреждение. Так что, -ig для gbak используется только в крайнем случае – когда поврежденная база починена утилитой gfix, но обычный backup не проходит. Только тогда имеет смысл повторить бэкап с опцией -ig.
-m
Сохраняет только метаданные (описания таблиц, процедуры, триггеры и т. д.). Данные в резервную копию не сохраняются. Используется когда вам нужно сделать копию пустой БД.
Однако, при этом могут не сохраняться значения генераторов. В последних версиях Firebird и InterBase это исправлено, но если нет – при восстановлении такой копии вы можете получить «мусор» в значениях генераторов (не 0, а случайные значения). Проверьте вашу версию Firebird или InterBase на наличие или отсутствие данного бага.
-limbo
Не сохраняет в резервной копии БД версии записей, которые созданы транзакциями, находящимися в состоянии in limbo. Такое состояние может быть только у не завершившихся транзакций двухфазного коммита (2PC). Если приложения не используют двухфазный коммит, или вы не знаете, что это такое, то этот параметр вам никогда не понадобится.
Примечание. Если требуется сделать резервные копии сразу несколько баз, то нужно выполнить команду gbak -b для каждой базы данных отдельно, но ни в коем случае не указывать нечто вроде gbak -b *.gdb *.gbk. Шаблоны и маски в данном случае не работают.
-y
Выше уже были приведены примеры перенаправления вывода в файл этой командой, однако, если просто в окне cmd (Windows) эта команда работает нормально, то при ее использовании в bat/cmd командном файле ошибки могут не сохраняться в файл, указанный в опции -y. Вы можете отказаться от этой опции, используя перенаправление вывода самостоятельно, в соответствии с документом http://technet.microsoft.com/ru-ru/library/bb490982(en-us).aspx
Другие параметры gbak – InterBase 2007 и выше
В InterBase 2007 введена возможность создания резервных копий, аналогичная nbackup в Firebird 2. В то время как nbackup является в Firebird отдельной утилитой, функции, похожие на nbackup, в InterBase выполняет gbak. Вот краткое описание новых опций:
выполнить онлайн-дамп базы данных в файл . Результатом будет копия базы данных в файле . Эта база по умолчанию находится в состоянии read-only. Если уже существует, то в него будут перенесены изменения, произошедшие в базе данных с момента предыдущей операции дампа (gbak -d)
перезаписать целиком, если он существует.
Подробнее о других опциях gbak (-archive_journals, -archive_database, -archive_recover, -archive_dumps) и новых функциях InterBase 2007 читайте в документе.
Services API – backup
По умолчанию gbak «прокачивает» данные через себя, как изображено на картинке:
Однако, в InterBase 6 было «опубликовано» Services API для выполнения сервером по команде действий, аналогичных выполняемым утилитами командной строки gbak, gfix, gsec. «Опубликовано» потому, что это API присутствовало в InterBase 5, но было секретным, и никак не использовалось программами, сопровождающими IB.
Примечание. Services API – это, например, закладка компонент InterBase Admin в Delphi (компонент IBBackupService, например), компоненты pF. Service в FIBPlus (pFIBBackupService), также, IBExpert выполняет backup/restore только при помощи Services API, и т. д. Грубо говоря, если приложение не вызывает gbak.exe, но может делать backup, restore, и другие подобные «серверные» действия, значит оно использует Services API. И gbak.exe тоже использует Services API, если указана опция -se (см. далее).
Теперь (c 2000 года, с момента выхода InterBase 6.0) InterBase и Firebird могут делать так:
gbak или программа, использующая Services API, отправляет серверу команду, а сервер ее выполняет сам. В этом случае программа, отдавшая команду, может получать лог выполнения от сервера и выдавать все что сообщит о процессе сервер.
gbak -b -g -se server:service_mgr c:\db\e.fdb d:\bak\e.fbk .
-se – это и есть команда серверу, чтобы не gbak, а сам сервер выполнил резервное копирование.
server – имя компьютера, где находится сервер InterBase или Firebird (если на этом же, то можно указать localhost). server можно не указывать, если сервер «локальный», и работает локальный протокол:
gbak -b -g -se service_mgr c:\db\e.fdb d:\bak\e.fbk .
:service_mgr – имя интерфейса Services API, оно обязательно, неизменно, и пока только одно. Может быть в дальнейшем появится что-то еще, но пока есть только то что есть.
- пути к базам (или алиасы) должны быть указаны только серверные, как для базы так и для файла резервной копии. Имя сервера к имени БД добавлять не нужно, т. к. оно уже должно быть указано как опция команды -se
- у сервера должны быть права на запись туда, куда сохраняется резервная копия. На Windows сервер по умолчанию стартует под учетной записью LocalSystem, которая не имеет и не может иметь прав на внешние ресурсы (например, шаренные папки). Поэтому, если вы хотите сохранять резервные копии БД на другой компьютер сразу, а не путем копирования получившегося на сервере файла backup – нужно создать пользователя (например firebird), дать этому пользователю права на папки установки сервера, папки с базами данных и папки с резервными копиями, и затем остановить сервер и запустить его указав в параметрах сервиса новое имя пользователя.
Заключение по backup
Резервное копирование – «онлайновая» операция, т. е. может быть выполнена в любой момент, во время работы пользователей с БД. Эту операцию можно и нужно автоматизировать, сделав резервное копирование регулярным. Без резервных копий вы рискуете остаться ни с чем, если база данных окажется повреждена по какой-либо причине.
Отсюда же следует, что категорически нельзя делать резервные копии на тот же самый логический диск, где находится база данных. Еще лучше делать резервные копии на другой физический диск, поскольку чтение и запись будут разделены, и это даст как минимум 30% ускорение процесса резервного копирования.
Восстановление базы данных из резервной копии – restore
Операция, обратная резервному копированию:
gbak -c e.fbk e.fdb
- Cервер создает пустую базу данных e.fdb. Причем, создает ее в том формате баз данных, который является для него «родным». Пустая база данных будет содержать все таблицы rdb$ (пока пустые), и будет иметь ряд параметров, например, такие как размер страницы, forced write и т. д., которые или взяты из резервной копии, или установлены в командной строке gbak.
- Cервер считывает метаданные (описания таблиц и индексов, процедур) из резервной копии и переносит их в базу данных.
- Cервер считывает данные из резервной копии и переносит их в базу данных
- Cервер считывает остальные метаданные (триггеры, гранты, check constraints и т. п.) из резервной копии и переносит их в базу данных
- Cервер создает (активирует) все индексы таблиц (которые были активны в момент создания резервной копии)
Помните, что если вы делаете восстановление на новой версии сервера, например, резервную копию делали на Firebird 1.5 (формат БД ODS 10.1), а восстанавливаете на Firebird 2.1 (формат БД ODS 11.1), то база будет создана в формате, поддерживаемом по умолчанию Firebird 2.1, и Firebird 1.5 с этой базой работать не сможет.
Резервные копии, кстати, тоже имеют свой формат, и резервная копия БД, сделанная например в Firebird 2.1 утилитой gbak этой же версии, не может быть восстановлена утилитой gbak от Firebird 1.5. Подробнее варианты переноса резервных копий и баз между версиями серверов описаны в документе.
Примечание. Если вас интересует точная последовательность действий gbak при backup и restore, например, порядок сохранения и восстановления объектов метаданных, то вы можете обратиться к исходным текстам – backup.epp и restore.epp соответственно. По мере развития IB/FB и исправления ошибок порядок сохранения-восстановления некоторых объектов изменялся (например, udf стали идти в бэкапе «раньше» некоторых других объектов).
Примечание. Существует возможность при восстановлении создать многофайловую базу данных. Однако, такая функциональность была нужна когда были распространены файловые системы, не поддерживавшие файлы более 2-4 гигабайт, а также когда InterBase не поддерживал как базы так и бэкапы более 4-х гигабайт. В настоящее время нет никакого смысла создавать как многофайловые бэкапы, так и многофайловые базы данных, поэтому подобная функциональность в данной статье не описана.
Дополнительные параметры restore
| Опция | Назначение | |
|---|---|---|
| -c[reate] | создать (восстановить) базу данных из резервной копии | |
| -bu[ffers] n | изменить (или указать новый) размер кэша БД. Принимается значение больше 0. | |
| -p[age_size] n | указать новый размер страницы для базы данных | |
| -i[nactive] | не активировать индексы | |
| -k[ill] | не создавать (и удалить) имеющиеся у базы данных shadow | |
| -m[etadata] | восстановить только метаданные (без данных) | |
| -use_[all_space] | максимально заполнять страницы данных (для read-only баз). Обратного ключа нет. | |
| -mo[de] | восстановить в режиме read_only или read_write (по умолчанию read_write) | |
| -o | делать commit после восстановления каждой таблицы | |
| -no_validity | не выполнять контроль данных (InterBase 6, Firebird, Yaffil) | |
| -va[lidate] | выполнять контроль данных (InterBase 7.x, 2007, 2009), по умолчанию контроль не выполняется | |
| -user | имя пользователя, SYSDBA или владельца БД | |
| -pas[sword] | пароль пользователя | |
| -v | полный вывод лога действий | |
| -y | вывод лога в файл | |
| Новая опция Firebird 2.1 | -nodbtriggers | отключает срабатывание триггеров уровня базы данных. Эту опцию может указать только SYSDBA или владелец БД |
| Дополнительные опции Firebird 2.5 для исправления кодировки метаданных – автоматизация действий, которые при переходе с предыдущих версий на Firebird 2.1 нужно выполнять вручную (скриптом в папке установки misc\upgrade\metadata). | -fix_fss_d[ata] | исправить кодировку данных |
| Обе опции -fix_* указываются ОДИН раз в том случае, если при восстановлении бэкапа возникает ошибка malformed string. При указании этих опций повторно при backup/restore база данных будет испорчена. | -fix_fss_m[etadata] | исправить кодировку метаданных, например, -fix_fss_metadata win1251 |
| Дополнительная опция InterBase 2007 | -pr[eallocate] n | Изменить или установить размер преаллокирования базы данных, где n – новое минимальное число страниц, из которых будет состоять файл базы данных. ! «Преаллокирование» на самом деле «добивает» базу данных до заданного количества страниц после выполнения restore, а не до заливки данных в БД. |
| Дополнительная опция InterBase 2009 | -decrypt | расшифровать зашифрованный бэкап. Подробнее читайте Data Definition Guide, раздел Encrypting backup files. |
| Дополнительная опция InterBase 2009 | -sep |
Что здесь отсутствует? Правильно, знакомый многим параметр -r. Параметр -r на самом деле не -r[estore], а -r[eplace], т.е. не «восстановить», а «заменить» имеющуюся базу данных. Т.е. если в предыдущем примере команды заменить -c на -r, то существующая база данных e.fdb будет молча удалена. Этого допускать нельзя, потому что по разным причинам восстановление из резервной копии может не состояться, и тогда вы останетесь без оригинальной базы данных и с невосстановимой резервной копией.
Интересно, что иногда у людей в командной строке восстановления БД из резервной копии можно встретить и такой оксюморон:
gbak -c -r e.fbk e.fdb
Причина написания такой командной строки кроется в неверном чтении документации по InterBase. Там указано
gbak <-c|-r>[options] source dbfile
Что означает – «или -c, или -r», но никак не оба вместе. Тем не менее, лучше такие неоднозначности не устраивать.
Кроме того, в Firebird 2.0 параметр -r сам по себе был фактически запрещен, т. к. «убиение» оригинальных баз данных при помощи -r имеет массовый характер. Теперь в Firebird 2.0 параметр -r просто не работает, и вместо него нужно использовать явно -rep (или -replace_database полным текстом), или -r o (-recreate_database overwrite).
- gbak -b -g e.fdb e.fbk
- переименовать e.fdb например в tmp.fdb
- gbak -c e.fbk e.fdb
Поборники параметра -r могут сказать, что они или выполняют пункт 2, или вместо пункта 2 копируют базу данных в другой файл (остановив сервер InterBase или Firebird, разумеется). На это могу сказать следующее – все равно использовать -r не надо. Во-первых, он несовместим с Firebird 2.0, и во-вторых, что будет, если переименование или копирование вдруг произойдет с ошибкой?
Теперь можно перейти к более подробному описанию параметров restore.
-bu n
Изменить размер кэша базы данных. По умолчанию кэш базы данных задан в файле конфигурации сервера (firebird.conf, ibconfig), и равен 2048 страниц. Это значение действует для всех баз данных, у которых размер кэша задан неявно. Если вы используете на сервере несколько баз данных, то может потребоваться указать для них разный размер кэша, в зависимости от назначения этих баз. Параметр -bu n позволяет при восстановлении базы данных задать или изменить этот размер. К сожалению, у gbak можно указать значение -bu только больше 0. Если вы обнаружили, что в бэкапе уже «зашито» значение кэша, то «сбросить» его при restore не получится. Для убирания размера кэша в БД придется использовать gfix.
Если размер кэша вообще задан в БД (а в большинстве случаев это не делают), то этот параметр используется обычно при переносе базы данных, например, со старого сервера на новый, или при переносе БД между архитектурами Classic и SuperServer.
Эквивалентно команде gfix -bu n.
-p n
Позволяет задать новый размер страницы базы данных. Это единственный способ, которым можно изменить размер страницы БД. На текущий момент можно сказать следующее – если вы посмотрели параметры БД через gstat -h, и увидели, что у базы данных размер страницы 1024 или 2048 байт – рекомендуется сделать backup и restore с указанием размера страницы 4096, 8192 или 16384 байт (если ваша версия сервера поддерживает страницы в 16к). Потому что даже небольшие базы данных с таким небольшим размером страницы имеют явно худшую производительность, чем базы со страницей 4 килобайта и выше.
Сервер сохраняет размер страницы БД при создании резервной копии, поэтому повторно указывать размер страницы при restore нет необходимости.
Не вставляйте этот параметр в «автоматизированную командную строку restore», потому что если вы захотите изменить размер страницы текущей БД вручную, то «автоматизированный restore» поменяет ее обратно.
-i
Не выполнять создание (активацию) индексов (последняя фаза restore). После восстановления базы данных все индексы в ней останутся отключены (неактивны). Фактически с такой базой данных работать нельзя, т. к. при отключенных индексах Primary key, Foreign key и Unique возможны нарушения целостности данных в таблицах (дублирование первичных ключей и т. д.).
Данный параметр имеет смысл использовать разве что в специфических целях – например, восстановить только данные из бэкапа за максимально быстрое время, или определить длительность создания всех индексов (замерить время gbak -c, затем замерить время gbak -c -i, после чего вычесть одно время из другого – получите длительность активации всех индексов), чтобы определить или текущую производительность каталога temp, или сравнить ее с явно заданным в конфигурации расположении temp на другом физическом диске.
Если вы восстановили бэкап с опцией -i, индексы можно активировать командой alter index nnn active (для каждого индекса).
-k
Не создавать shadow, если таковые были созданы в оригинальной базе данных. На самом деле этот параметр не только «не создает» shadow, но и еще удаляет существующие, например в варианте с backup/restore с промежуточным переименованием базы данных. Впрочем, поскольку использовать shadow (программный raid 1) сейчас нет смысла, то и параметр -k можно считать атавизмом.
Эквивалентно команде gfix -kill.
-m
Восстановить только метаданные, без данных. Можно использовать как «проверочный» метод целостности резервной копии, или отсутствия проблем в метаданных.
-mode
По умолчанию база данных восстанавливается в режиме read_write. Однако, если вам нужно получить базу только для чтения, особенно для размещения ее на CD или DVD, то можно воспользоваться -mode read_only.
Эквивалентно команде gfix -mode read_write/read_only.
-use_
По умолчанию базы данных InterBase и Firebird резервируют примерно 30% пространства на страницах данных, для размещения версий при будущих вставках, удалениях или обновлениях записей. Если предполагается запись базы данных на CD или DVD, то лучше базу данных несколько «сжать», указав параметр -use_ при restore (одновременно указав -mode read_only).
Эквивалентно команде gfix -use full. Обратная команда (снятие режима максимального заполнения страниц) – gfix -use reserve.
Внимание! При помощи restore вы не можете указать -use reserve, такой опции у gbak при восстановлении нет ни у InterBase, ни у Firebird.
-o
Помогает при некоторых случаях «невосстановимого backup». Тут больше добавить нечего.
-n
Отключает проверку constraints, если при обычном восстановлении БД оказалось, что логическая целостность оригинальной БД была повреждена (например, из-за битого индекса PK возникли дубликаты первичного ключа).
Крайне не рекомендуется для использования в «командной строке автоматизированного restore».
-va
В InterBase 7.x, 2007 и 2009 при восстановлении БД из резервной копии параметр -n (см. выше) включен по умолчанию. Это опасно тем, что можно не заметить появление в базе данных нарушений целостности Primary key, Foreign key и Unique в случае повреждения оригинальной базы данных. Поэтому в данных версиях InterBase параметр -va рекомендуется использовать всегда, кроме случаев восстановления «невосстановимого backup».
Примечание. Если требуется восстановить сразу несколько баз из бэкапов, то нужно выполнить команду gbak -c для каждой базы данных отдельно, но ни в коем случае не указывать нечто вроде gbak -c *.gbk *.gdb. Шаблоны и маски в данном случае не работают.
-fix
Опции -fix_fss_metadata и -fix_fss_data у Firebird 2.5 предназначены для приведения чарсета метаданных (и данных), которые были записаны в некорректной кодировке. Например, при редактировании процедур или триггеров в код могли попасть комментарии или константы в кодировке none, в то время когда они на самом деле являются символами 1251.
Если при restore gbak выводит сообщение об ошибке
Malformed string
то нужно принудительно указать нужную кодировку при помощи указанных опций. После этого в столбцах Unicode данные будут записаны корректно.
gbak от Firebird 2.5 также может выдавать сообщение
gbak:Invalid metadata detected. Use -FIX_FSS_METADATA option.
что сигнализирует об аналогичной ситуации, и требует явного указания данной опции с нужной кодировкой.
Внимание! Указывать опции -fix. можно ТОЛЬКО ОДИН РАЗ! Если вы сделаете еще раз backup/restore этой же базы данных с этими опциями, то исходные тексты процедур и триггеров БУДУТ ИСПОРЧЕНЫ!
Другие параметры gbak – InterBase 2007 и выше
-preallocate n
весьма странная опция, учитывая то, что она «добивает» базу данных до указанного в n размера страниц, а не аллокирует сразу эти страницы в момент начала restore. Физически это выглядит следующим образом:
gbak -c -pr 1300000 db.gbk db.gdb.
- сначала пройдет restore
- в конце restore сервер добьет базу нужным числом страниц до заданного размера. Если размер страницы базы db.gdb был 4096 байт, то размер файла будет ровно 5324800000 байт (1.3 млн страниц умножить на 4096. то есть, к счастью, preallocate не плюсует размер преаллокирования к размеру БД).
Одновременно, если вы поменяете при restore размер страницы, автоматически изменится и значение preallocate, чтобы соблюсти заданный размер независимо от размера страницы.
Если вы делаете restore бэкапа рабочей базы себе на компьютер, то сначала посмотрите gstat -h db.gdb, нет-ли там опции preallocate. Если есть – при restore придется указать -pr 0, иначе сервер развернет базу у вас на компьютере в полный размер preallocate.
Services API – restore
Здесь все то же самое, что и при создании резервной копии:
gbak -c -se server:service_mgr d:\e.fbk c:\db\e.fdb
Восстановление (например, проверочное) на тот же самый диск, где находится резервная копия, не так опасно, как в случае backup (когда свободное место может кончиться, и резервная копия будет неполной, да еще и база данных может быть повреждена). Но разумеется имеет те же самые проблемы с производительностью, когда восстановление проводится на тот же самый физический диск (поочередные чтение и запись с разных участков диска). Поэтому при восстановлении базы данных из резевной копии рекомендуется использовать разные физические диски.
Ошибки при restore
- на этапах 1 и 2 (создание БД и создание описаний таблиц и индексов) ошибки вряд ли могут произойти. Разве что если вы пытаетесь создать БД там, где это сделать невозможно – нет прав, read-only носитель и т. п.
- на этапе 3 (заливка данных) могут быть ошибки, которые «чинятся» повтором restore с параметром -o
- на этапе 4 (заливка процедур, триггеров и т. п.) могут быть ошибки, связанные с некорректным blr (двоичным кодом) процедур и триггеров. Текст процедур и триггеров в этот момент никакого значения не имеет, он даже может отсутствовать в оригинальной базе и резервной копии.
- на этапе 5 (создание индексов) могут быть ошибки, связанные с нарушением целостности первичных, вторичных и уникальных ключей (повреждения индексов в базе). До Firebird 2.0 такие ошибки приводили к прекращению restore, и в базе оказывались неактивными все индексы, шедшие после «проблемного». Firebird 2.0 продолжает активирование индексов после такой ошибки.
Если в БД не оказалось процедур или триггеров, то их надо извлечь в виде скрипта из оригинальной базы, и создать в новой БД. Если в БД нет части индексов, то их надо пробовать активировать по очереди (вручную), одновременно корректируя данные, которые препятствуют созданию соответствующего индекса (дубликаты первичного ключа, отсутствующие данные для вторичного ключа, и т. д.)
Хуже, если резервная копия оказывается битой сама по себе. В данном случае сможет помочь только инструмент IBBackupSurgeon, который позволяет «вытащить» все что было в резервной копии, полностью или по частям, даже если резервная копия имеет повреждения «посередине».
Заключение по restore
Никогда не используйте параметр -r. Всегда используйте -v – это поможет вам определить в случае ошибки, что восстановилось из БД, а что нет. Если во время restore произошла ошибка, то база данных будет в состоянии shutdown, т. е. к ней сможет присоединиться только SYSDBA или владелец БД. Поэтому невозможность для обычных пользователей подсоединиться после restore может служить дополнительным сигналом, что восстановление не прошло нормально, если вы не проверяете логи restore.
Как правило, restore по времени занимает в 2-4 раза дольше, чем backup. Это не относится к восстановлению из резервных копий nbackup или online dump.
Замечание по Services API
Вы уже в курсе, что можно заставить сервер делать backup или restore, через Services API – компонентами или утилитой gbak с опцией -se.
- для gbak -b/-c достаточно принудительно снять (завершить) процесс gbak.exe, или если он запущен интерактивно, нажать в окне cmd Ctrl-C. Поскольку backup или restore выполняется не сервером, а утилитой gbak, этот процесс будет прекращен.
- для backup и restore, выполняемых через Services API, это возможно только остановкой сервера, т. к. именно он выполняет этот процесс.
Автоматизация резервного копирования
Автоматизацию резервного копирования можно выполнить как самостоятельно, так и при помощи готовых инструментов. Например, как готовое решение можно использовать наш FBDataGuard Community Edition, который не только защищает базу данных от повреждений, но и может делать резервные копии по расписанию, тестовое восстановление, а также отправку уведомлений по email, и много других полезных вещей. Кроме него, разумеется, есть ряд других инструментов для автоматизации резервного копирования (только), но здесь мы их рассматривать не будем.
- команда gbak -b database.gdb database.gbk сотрет имеющуюся резервную копию с именем database.gbk
- не рекомендуется сохранять резервную копию на тот же самый логический диск, где находится база данных. Исключением можно считать одинокий клиентский компьютер, у которого есть только один диск C:.
Создаем файл backup.cmd. В файле должна быть одна команда создания резервной копии БД, возможно с параметром, указывающим некое число или день.
@echo off
set DOW=%1
del d:\backup\data%DOW%.log
c:\interbase\bin\gbak -b -g -user sysdba -pass masterkey localhost:c:\db\data.gdb
d:\backup\data%DOW%.gbk -v -y d:\backup\data%DOW%.log
Здесь всего три строки – последние «две» на самом деле одна строка, здесь разбита на две части для облегчения читаемости. Полные пути прописаны для того, чтобы backup.cmd можно было вызвать из любого каталога.
Если мы вызовем командный файл как
backup.cmd 1
то в результате в каталоге d:\backup будет создана резервная копия data1.gbk и лог data1.log.
Теперь автоматизируем вызов at. Можно открыть окно командной строки (Пуск, выполнить, cmd), а можно открыть в Панели управления окно планировщика задач и задать нужные параметры интерактивно. Я приведу текст командного файла conf_at.cmd, который автоматически задает для AT создание резервных копий каждый день недели:
at %1 /every:M c:\backup.cmd Mon
at %1 /every:T c:\backup.cmd Tue
at %1 /every:W c:\backup.cmd Wed
at %1 /every:Th c:\backup.cmd Thu
at %1 /every:F c:\backup.cmd Fri
at %1 /every:S c:\backup.cmd Sat
at %1 /every:Su c:\backup.cmd Sun
Теперь можно вызвать этот командный файл как
conf_at 03:00
В результате каждый день недели ровно в 3 часа ночи at будет запускать backup.cmd с соответствующим параметром. И мы в каталоге d:\backup получим т. н. «револьверный» бэкап, то есть по одной резервной копии на каждый день недели, которые будут перезаписываться каждый день.
Имена резервных копий будут dataMon.gbk, dataTue.gbk и т. п., что не совсем удобно при просмотре каталога. Вместо Mon, Tue и так далее можно задать номера дней 1, 2, 3. только главное не забыть, какой день недели у вас соответствует цифре 1.
Это самый примитивный вариант, который не обрабатывает ошибки при выполнении резервного копирования. Если вы не будете проверять логи бэкапа, то может оказаться что все резервные копии «дефективные». Поэтому нужно не только регулярно проверять логи, но и периодически делать тестовое восстановление например из самой последней резервной копии.
Если backup делается на другой компьютер, то нужно задавать команды AT от имени пользователя, который имеет право доступа к разделяемой папке на этом компьютере. Также можно добавить обработку ошибок в backup.cmd, даже с отправкой email в случае ошибки, но это выходит за рамки статьи.
Вот здесь еще один пример автоматизации, более сложный, с тестовым восстановлением, уведомлением по email, обработкой ошибок. Разумеется, в качестве готового решения он не годится, но вполне подходит как пример.
Автоматизированное восстановление
На самом деле зло. Что, если автоматический бэкап завершился с ошибкой? Что будет, если при автоматизированном восстановлении возникнет ошибка?
Крайний случай – бэкап все время в один и тот же файл, восстановление с ключом -r, да еще и все это на одном логическом диске. Как результат (случившийся в одной компании) – неполный бэкап и убитая база.
Поэтому, если вы зачем-то делаете автоматизированное восстановление, то оригинальную базу ни в коем случае с «рабочего места» удалять нельзя, ее нужно переименовывать и оставлять на месте до тех пор, пока не будет сделано очередное резервное копирование новой базы.
Соответственно, примеров автоматизированного восстановления не даю. Схематически верный вариант изложен в разделе об опциях restore.
Есть вопросы по статье? Присылайте на support@ibase.ru.
Запрещается перепечатка, перевод и копирование. Разрешается частичное цитирование с обязательной ссылкой на источник www.ibase.ru/gbak/
Copyright iBase.ru © 2002-2023
Корки странно читаются на разных машинах
Версии софта в centos6 и rhel6 совпадают, согласно диффанью выхлопа rpm -q.
Когда читаю корку с rhel6, что под убунточкой, что под centos6 получаю различия выхлопа вполть до разной глубины стектрейса и количества потоков.
Как такое вообще может быть, куда смотреть? Что влияет на формат core dump’a и то как оно читается, и где про это почитать?
Корки смотрел как от падений, так и снятые gcore. Бинари я ессно проверил что одни и те же.
Тащу корку с помощью scp, предварительно пожав gzip’om.
Версии gdb везде 7.11.

pon4ik ★★★★★
10.06.16 15:29:37 MSK

Легко. В корке нет отладочных символов, они загружаются из той системы, в которой ты исследуешь core дамп. Так что либо воспроизводи систему в точности, либо исследуй core дампы прямо на месте.
i-rinat ★★★★★
( 10.06.16 15:33:14 MSK )
Пример можешь дать (вывод bt того же на разных машинах)? Интересно, хотя я не удивлен
anonymous
( 10.06.16 15:36:22 MSK )
Ответ на: комментарий от i-rinat 10.06.16 15:33:14 MSK
Так бинарник ведь и тот же он таскает, не?
anonymous
( 10.06.16 15:39:10 MSK )
На машинах разные библиотеки, в основном это касается libc. Нужно брать оригинальные rpm пакеты от rhel6, распаковывать и подсовывать gdb, иначе он возьмёт их от убунты — а они то наверняка собраны иначе и бинарно не совпадают.
mashina ★★★★★
( 10.06.16 16:21:17 MSK )
Последнее исправление: mashina 10.06.16 16:21:47 MSK (всего исправлений: 1)
Ответ на: комментарий от anonymous 10.06.16 15:39:10 MSK

Я как-то раз пока пакет с отладочными символами ставил, обновил libc6, но сразу не заметил. Все вызовы в bt поплыли.
i-rinat ★★★★★
( 10.06.16 16:25:26 MSK )
Ответ на: комментарий от i-rinat 10.06.16 15:33:14 MSK

Отладочные символы же есть в бинарях. Более того, я специально проверял для других раскладов, например centos6 vs ubuntu 14.04 на разных машинах и оно работало.
pon4ik ★★★★★
( 10.06.16 16:36:39 MSK ) автор топика
Ответ на: комментарий от anonymous 10.06.16 15:39:10 MSK

Кстати вот нагуглил:
> And this is what i get after i scp the exe and dump to a different > computer (a kubuntu box): > (gdb) bt > #0 0xffffe410 in __kernel_vsyscall () > #1 0x4017a101 in modff () from /lib/libc.so.6 > #2 0x4017b8e8 in sigorset () from /lib/libc.so.6 > #3 0x400ed794 in ?? () . > As you can see, the backtraces differ, and i lose almost all symbols. > What am i doing wrong? You aren't necessarily doing anything wrong. The core dump contains memory image of the various writable (data) segments of the process, but it does not contain copies of the executable code (read-only sections), to save space [1]. Because of that, gdb backtrace requires access to the *exact* version of all executable sections that were used when the core dump was produced. This means that you need to tell gdb where to find the main executable *and the shared libraries* which were used by the running process, so it can extract symbol table from them, and decode addresses in the core-dump into symbol names. Without matching shared libraries, gdb just uses whatever libraries are installed on the current system, if these don't match what's in the dump, you get "garbage". So, copy all the shared libraries (use gdb "info shared" to find what they are) from the "original" computer to a subdirectory on the second one (DO NOT overwrite /lib/libc.so.6 or any other libs on the second computer -- that will likely render it unbootable), and tell gdb to use them with gdb "solib-absolute-prefix". From "info gdb": `set solib-absolute-prefix PATH' If this variable is set, PATH will be used as a prefix for any absolute shared library paths; many runtime loaders store the absolute paths to the shared library in the target program's memory. If you use `solib-absolute-prefix' to find shared libraries, they need to be laid out in the same way that they are on the target, with e.g. a `/usr/lib' hierarchy under PATH. For example, if "info shared" says: From To Syms Read Shared Object Library 0x004880c0 0x0048d590 Yes /lib/tls/librt.so.1 0x00b74890 0x00c56f48 Yes /lib/tls/libc.so.6 0x00daa2f0 0x00db2608 Yes /lib/tls/libpthread.so.0 0x00b477a0 0x00b58a47 Yes /lib/ld-linux.so.2 then do this: # on "original" computer: cd / tar czf /tmp/to-copy.tgz \ path/to/exe path/to/core lib/tls/librt.so.1 \ lib/tls/libc.so.6 lib/tls/libpthread.so.0 lib/ld-linux.so.2 # on the "second" computer: mkdir /tmp/libs.orig; cd /tmp/libs.orig tar xvzf to-copy.tgz gdb path/to/exe set solib-absolute-prefix /tmp/libs.orig core path/to/core where # should give reasonable back trace Cheers, [1] Solaris allows inclusion of executable sections into core with coreadm(1), but I don't believe such capability exists in linux.
i-rinat ★★★★★
( 10.06.16 16:40:55 MSK )
Ответ на: комментарий от pon4ik 10.06.16 16:36:39 MSK

специально проверял для других раскладов
IMHO, это лотерея.
i-rinat ★★★★★
( 10.06.16 16:43:06 MSK )
Ответ на: комментарий от anonymous 10.06.16 15:36:22 MSK

Примерно так: не для всех потоков глубина стека отличается, но учитывая что и известные фреймы матчаться на разные части одного и того же бинаря это не очень важно 🙂
gdb thread apply all bt Thread 40 (Thread 0x7f6972a2c700 (LWP 34689)): #0 0x000000385ea0b98e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 #1 0x00007f69740db410 #2 0x00000000025eaf10 #3 0x0000000002f2e858 #4 0x00007f6972a2bd10 #5 0x000000385f203e46 #6 0x000000000003fc8d #7 0x00000000025eaf10 #8 0x000000041410351a #9 0x0000000002f2e820 #10 0x0000000002f2e888 #11 0x00000000025eaf10 #12 0x00007f69740d87e1 #13 0x00007f6972a2c9c0 #14 0x000000385de14725 in _dl_close_worker () from /lib64/ld-linux-x86-64.so.2 .
и такой вот на удалённой машине:
Thread 40 (Thread 0x7f6972a2c700 (LWP 34689)): #0 0x000000385ea0b98e in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0 #1 0x00007f69740db410 in #2 0x00007f69740d87e1 in #3 0x00007f69740cbad7 in #4 0x00007f69740cbc89 in #5 0x000000385ea079d1 in #6 0x000000385e6e8b6d in
pon4ik ★★★★★
( 10.06.16 16:44:47 MSK ) автор топика
Ответ на: комментарий от mashina 10.06.16 16:21:17 MSK

Ну с убунтой — поверю. А как быть с контейнером с центосью? Они же обещают бинарную совместимость, хм.
pon4ik ★★★★★
( 10.06.16 17:01:27 MSK ) автор топика

Вообщем общую идею уловил, попробую прост папку с либами утащить as-is с rhel
pon4ik ★★★★★
( 10.06.16 17:03:01 MSK ) автор топика
Ответ на: комментарий от pon4ik 10.06.16 17:01:27 MSK
Ну с убунтой — поверю. А как быть с контейнером с центосью? Они же обещают бинарную совместимость, хм.
Бинарная совсестимость пакетов это не то же самое, что и бинарная идентичность секций кода в библиотеках. Так что с centos нужно делать аналогично.
Вообщем общую идею уловил, попробую прост папку с либами утащить as-is с rhel
Проще брать два rpm с libc (сама либа + debug символы) и распаковывать их в отдельной директории. libс кидает файлы по многим путям и руками набирать конетнт может оказаться не очень удобно.
mashina ★★★★★
( 10.06.16 17:22:52 MSK )
Ответ на: комментарий от mashina 10.06.16 17:22:52 MSK
Интересно, а почему в адреса в трейсе разные? GDB трейс не из %rbp строит? Понятно было бы, если функции разные, а тут и адреса тоже другие. Библиотеки всё равно одинаковые нужны, но всё же
anonymous
( 10.06.16 17:54:06 MSK )
Ответ на: комментарий от anonymous 10.06.16 17:54:06 MSK

Из rbp берётся же только адресс верхушки, и он как раз одинаковый.
pon4ik ★★★★★
( 10.06.16 18:01:35 MSK ) автор топика
Ответ на: комментарий от mashina 10.06.16 17:22:52 MSK

Да, хорошая идея, спасибо. Там не только libc, но думаю лучше для всего так сделать.
pon4ik ★★★★★
( 10.06.16 18:02:23 MSK ) автор топика
Ответ на: комментарий от pon4ik 10.06.16 18:01:35 MSK
В %rbp предыдущее значение %rbp, в %rbp+8 — return point. Как ещё можно стек раскрутить даже не знаю
anonymous
( 10.06.16 18:11:46 MSK )
Ответ на: комментарий от anonymous 10.06.16 18:11:46 MSK

да, чет не подумал. Кстати адреса начинают не сразу отличаться.
pon4ik ★★★★★
( 10.06.16 18:14:50 MSK ) автор топика
Ответ на: комментарий от anonymous 10.06.16 17:54:06 MSK
Интересно, а почему в адреса в трейсе разные? GDB трейс не из %rbp строит? Понятно было бы, если функции разные, а тут и адреса тоже другие.
%rbp, вообще говоря, может не быть с ожидаемым результатом, т.е. с началом адреса кадра, даже для текущей функции — фрейма может вообще не быть (-fomit-frame-pointer) или ф-я могла заюзать временно %rbp в месте останова для чего-либо.
да, чет не подумал. Кстати адреса начинают не сразу отличаться.
Почему именно тут gdb не разрулил хз, но вообще откат стека операция нетривиальная. И по трейсам видно что gdb начинает делать это как-то неправильно т.к. залезает на стек или в кучу (адреса типа 0x00007f6972a2bd10)
mashina ★★★★★
( 10.06.16 18:33:57 MSK )
Последнее исправление: mashina 10.06.16 18:34:54 MSK (всего исправлений: 1)
Ответ на: комментарий от anonymous 10.06.16 18:11:46 MSK
При оптимизации компилятор может выпиливать сохранение стекового кадра в rbp, если у функции нет локальных переменных (либо получилось их все распихать по регистрам). В этом случае без полной отладочной информации однозначно раскрутить стек нельзя.
KivApple ★★★★★
( 10.06.16 18:37:38 MSK )
Ответ на: комментарий от mashina 10.06.16 18:33:57 MSK
%rbp, вообще говоря, может не быть с ожидаемым результатом, т.е. с началом адреса кадра, даже для текущей функции — фрейма может вообще не быть (-fomit-frame-pointer) или ф-я могла заюзать временно %rbp в месте останова для чего-либо.
Точно, но тогда нормального трейса не вышло бы нигде))
Необычное переполнение жесткого диска или как удалить миллионы файлов из одной папки
Скорей всего, матерым системным администраторам статья будет не очень интересна. В первую очередь она ориентирована на новичков, а также на людей, которые столкнулись с подобной проблемой — необходимостью удалить огромное количество файлов из одной папки в ОС Linux (Debian в моем случае), а также с закончившимся местом на диске, когда df -h выдает что почти 30% свободно.
Начало
Ничто не предвещало беды.
Сервер с сайтом работал без никаких проблем уже больше года (uptime почти 500 дней), не было никаких проблем, и я с чистой душой спокойно ушел в отпуск.
В первый же день отпуска мне звонят с жалобой — сайт недоступен. MySQL падает с ошибкой Error 28 «No space left on device».
Казалось бы, проблема банальна — кончилось место на диске. Правда, df -h показывает, что на диске имеется вполне достаточное количество свободного места, ну да я же в отпуске, разбираться лень — посоветовал им поискать на диске ненужные файлы (старые бекапы и т.д.) и их удалить. Удалили, вроде все заработало.
Прошла пара часов и проблема вернулась. Странно — свободное место на жестком диске за это время практически не уменьшилось. После беглого гугления обнаружился топик на serverfault, в котором говорится, что проблема может возникнуть также из-за того, что кончилось не место на диске, а айноды!
Ввожу в консоль df -i — и оказывается действительно, айноды у меня закончились.
Проблема
Начал искать, где же у меня находится столько файлов на жестком диске, что они сожрали все айноды (а айнодов у меня на 500-гигабайтном жестком диске больше 30 миллионов).
И нашел — оказалось, проблема была в папке с сессиями php.
Видимо, по какой-то причине сломался механизм автоочистки этой папки, что привело к тому, что в ней скопилось огромное количество файлов. Насколько огромное — сказать сложно, потому что никакие стандартные команды линукс, такие, как ls, find, rm и т.д. — с этой папкой не работают. Просто виснут, заодно подвешивая весь сервер. Могу только сказать, что сам файл директории стал весит около гигабайта, а также что файлов там точно более полумиллиона, потому что столько я оттуда уже удалил.
Решение
Решение очевидное — надо удалить все эти файлы сессий. При этом желательно, чтобы сервер продолжал работать в штатном режиме. Для начала я переименовал папку сессий, в которой лежит куча файлов, а вместо нее создал пустую — чтобы спокойно из старой (переименованной) удалять все файлы, и чтобы это не мешало созданию новых файлов сессий.
Также в крон добавил автоматическое удаление файлов сессий старше одного часа, чтобы проблема больше не повторилась.
И перешел к основной проблеме — очистке жесткого диска.
Попробовал решение «в лоб»:
rm -rf ./*
Сервер повис, ничего не удалилось
Попробовал известный способ для удаления большого числа файлов
find . -type f -exec rm -v <> \;
Ничего, сервер виснет, файлы не удаляются.
А теперь что самое интересное — файловый менеджер mc достаточно успешно справлялся с задачей удаления этих файлов! То есть, когда запускаешь удаление папки — файлы удаляются, mc не виснет. Удаление идет со скоростью примерно 5 000 файлов в минуту, правда при этом создается огромная нагрузка на жесткий диск, что приводит к неработоспособности сервера.
А хотелось бы, чтобы эти файлы постепенно удалялись в фоновом режиме, и не мешали нормальной работе сайта.
Собственно, решение опять нашлось в гугле — Olark делится способом, как он отобразил список из 8 миллионов файлов в 1 папке, используя системный вызов getdents
Здесь находится документация по функции getdents, а также пример кода, который ее использует.
Правда, этот пример мне не совсем подошел — даже если ставить большой размер буфера, как советует Olark в своем блоге, все равно сервер виснет при попытке прочитать всю папку разом.
Опытным путем подобрал размер буфера в 30 килобайт, который позволяет считать около 550 названий файлов из директории, при этом не подвешивая сервер и не создавая излишней нагрузки на диск. А также немного переписал код примера, чтобы вместо отображения имени файла он его удалял.
В итоге у меня получился такой код:
#define _GNU_SOURCE #include /* Defines DT_* constants */ #include #include #include #include #include #include #define handle_error(msg) \ do < perror(msg); exit(EXIT_FAILURE); >while (0) struct linux_dirent < long d_ino; off_t d_off; unsigned short d_reclen; char d_name[]; >; #define BUF_SIZE 1024*30 int main(int argc, char *argv[]) < int fd, nread; char buf[BUF_SIZE]; struct linux_dirent *d; int bpos; int deleted; char d_type; char temp[100]; fd = open(argc >1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY); if (fd == -1) handle_error("open"); deleted = 0; nread = syscall(SYS_getdents, fd, buf, BUF_SIZE); if (nread == -1) handle_error("getdents"); if (nread != 0) < for (bpos = 0; bpos < nread;) < d = (struct linux_dirent *) (buf + bpos); d_type = *(buf + bpos + d->d_reclen - 1); if(d->d_ino && d->d_ino != 22332748 && d->d_ino != 22332761) < // тут я прописал inode самой директории и директории верхнего уровня, чтобы он не пытался удалять файлы "." и ".." - принимаю подсказки, как это сделать лучше sprintf(temp,"%s/%s", argv[1], (char *) d->d_name); remove(temp); deleted += 1; > bpos += d->d_reclen; > > printf("deleted %d\n", deleted); exit(EXIT_SUCCESS); >
Код компиллируется обычным gcc
gcc listdir.c -o listdir
И просто запускается из командной строки:
./listdir mod-tmp2
Получившийся файл я поставил в крон и теперь у меня удаляется по 547 файлов в минуту, при этом нагрузка на сервер в пределах нормы — и я надеюсь, в течение недели-другой все файлы все-таки удалятся.
Выводы
- Если df -h показывает, что на жестком диске еще есть место — его может и не быть. Надо смотреть также df -i
- Не стоит надеяться на механизмы авто-очистки таких вещей, как файлы сессий — в какой-то момент они могут не сработать, и вы окажетесь у целой горы файлов, удалить которые — задача нетривиальная
- Стандартные команды линукс, такие как ls, rm, find и т.д. могут пасовать перед нестандартными ситуациями вроде миллионов файлов в одной папке. В таком случае надо использовать низкоуровневые системные вызовы