Разбор всех заданий отборочной игры Yandex.Root

Сегодня ночью завершилась первая игра отборочного тура Yandex.Root — олимпиады для Unix-инженеров и системных администраторов. В ней приняло участие 456 человек из 229 команд, 194 из которых выполнили хотя бы одно задание. Со всеми девятью справилось 38 команд.Мы проводим Root её в четвёртый раз, но впервые решили опубликовать на Хабре разбор тасков. Задачи, которые мы даём на олимпиаде, сопоставимы с теми, что регулярно решают наши системные администраторы. В Яндексе почти каждый день что-то выкатывается и, когда что-то идёт не так, нужно оперативно распознать это и эффективно отреагировать.

6d34a2b1590449159129c06e45e3a04a.png

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

Мы будем благодарны, если вы нам об этом расскажете и поделитесь своим именем, как сделать лучше. Кстати, если хотите, то можете и попробовать себя в реальной игре. Вторая часть первого тура пройдёт через четыре дня — во вторник 14 апреля, и на неё ещё можно зарегистрироваться.

Игра ShannonМы решили назвать все игры в память о людях, которые внесли вклад в современные технологии, которые используются в нашей работе. Эта посвящена Клоду Шеннону, инженеру и математику, который среди прочего подарил нам слово «бит». Кстати, сам сервис root.yandex.ru запущен на compute узлах private cloud Яндекса.Цель отборочной игры — решить несколько проблем на виртуальной машине, изменив конфигурацию установленной ОС: например, запустить службу или скорректировать работу программы. Задачи могут быть как связанными, так и независимыми. Необходимо «зачистить мониторинг», то есть решить проблемы со статусом Critical (отмечены красным цветом) внутри виртуальной машины. Ее образ можно скачать заранее, образ зашифрован — ключ для расшифровки публикуется и рассылается всем участникам по электронной почте в начале игры.После расшифровки образа необходимо установить соединение с игровым VPN. Для этого всем участникам выдается config-файл: капитан получает его по почте в момент одобрения заявки, члены команды — когда принимают приглашение капитана. В случае утраты файл можно скачать повторно командой «download». Каждый игрок может подключиться к VPN со своей виртуальной машины, поэтому задачи можно распределять внутри команды и решать их параллельно.

Base В качестве операционной системы в этой игре используется ArchLinux. После загрузки ОС пользователь видит приглашение «shannon login:». Никаких подсказок относительно реквизитов доступа у игрока нет. Как правило, в таких случаях нужно воспользоваться наличием «физического» доступа к машине и сбросить пароль суперпользователя: перезагружаемся, останавливаем таймер обратного отсчёта в загрузчике Grub; нажимаем 'e', находим строчку linux…, дописываем в конец init=/bin/bash; нажимаем Ctrl-X, ждём загрузки; вводим команду passwd, устанавливаем новый пароль; вводим команду exec /sbin/init, загрузка продолжается. После выполнения этой процедуры можно войти в систему с новым паролем.Для решения задач потребуется установить некоторые пакеты, значит, нужно подготовить пакетный менеджер к работе:

синхронизируемся с внешним зеркалом: pacman-Sy, pacman-key --populate; обновляем пакетный менеджер: pacman -S pacman, pacman-db-upgrade; для решения некоторых заданий нам понадобится tcpdump и strace: pacman -S tcpdump strace. Внутри игрового образа находится программа game, которая запускает проверочные скрипты (далее — проверки) на удалённом сервере. В случае успешного выполнения проверки, игра засчитывает выполнение задания.

Чтобы обеспечить связность с удалённым сервером, нужно настроить OpenVPN. Организаторы уже подготовили всё необходимое — достаточно скопировать файл конфигурации (он прикреплён к письму от Yandex.Root) в /etc/openvpn/openvpn.conf и выполнить команду systemctl start openvpn@openvpn.

1.SSL Это задание было решено первым из всех. Справилась с ним команда SudariLudari. В задаче требуется сгенерировать сертификат, подписанный заданным сертификатом удостоверяющего центра.Set up a webserver with SSL Here is a private key and a certificate for a CA to generate your certificate:-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQCjKwGnBHUwQtTzLb5uhrh+eRRAQyQwGzCg+n4XWzt8M+iX/OGx4QCG4GjKhi9Nqzhm41+AjPB5cndU3Oe5j1LrcvWvxe2n15FG7hPSLG5dHe97pzpjKVma8OkcrUc6WWIccZ48FlV21ZCeUFukthtqEDDEEw1CxEnwHgIydnynlwIDAQABAoGADTAfrREmK6VrMtCCsMpAxTAiG+ORXDYGYyx73oVoNGy5ovc0gr0N3tjqf1wDHML3BxHfmTNLCHXhAUHtlMjpya7kkJELurrFgEQ9gkcdogcf8Iw/J6GjBpJG2WlXvVL4zEiYw0T5TULGI54Iest0ZQx88EX8r+6×1jI668RHCtECQQDYUPLf2K/0FUykcsXoKq1ECseSVpfhG5NITqsLOc93jh3xAQFYtSuM7E3CeHkP+ZoKY/SGd9QkWrhdQQFoGL5vAkEAwRoCwNqlUWwTVayGdgw/D/mxtFelKRYl8kj50MeMraBqHM/ijXZt+wF5exUmuPio+nF64UIqLA1VCYhnqJ49WQJAL3DJY0hdhnVpYqN9PeamK0cF79Un6AmpKnF+V67tDjZP4LwstGy/SV/FygGr41IFc4Pqa9c54mM3DdSk31SV5wJAHW9fmBI8PQsib17bKEd5nW/MfNcXYAn2QtaI7iBc+2KGilnOCQ5SeX6iC/cPbgbJi1OdDZVOZGSr38YhNvzYEQJBALoFJQEg6Xj44ClcJFIjbA+xyipk4h5JcmGvpUeKfaKFEBSJMECLR8wIa5XUkeRuM30JhTkd0s3WPUFaoBAvcvs=-----END RSA PRIVATE KEY----------BEGIN CERTIFICATE-----MIIDHzCCAoigAwIBAgIJALEwbIlKhnreMA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNVBAYTAlJVMQ8wDQYDVQQIEwZNb3Njb3cxDzANBgNVBAcTBk1vc2NvdzEPMA0GA1UEChMGWWFuZGV4MQ0wCwYDVQQLEwRSb290MRgwFgYDVQQDEw9yb290LnlhbmRleC5jb20wHhcNMTUwNDA2MTY0MzA5WhcNMTYwNDA1MTY0MzA5WjBpMQswCQYDVQQGEwJSVTEPMA0GA1UECBMGTW9zY293MQ8wDQYDVQQHEwZNb3Njb3cxDzANBgNVBAoTBllhbmRleDENMAsGA1UECxMEUm9vdDEYMBYGA1UEAxMPcm9vdC55YW5kZXguY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCjKwGnBHUwQtTzLb5uhrh+eRRAQyQwGzCg+n4XWzt8M+iX/OGx4QCG4GjKhi9Nqzhm41+AjPB5cndU3Oe5j1LrcvWvxe2n15FG7hPSLG5dHe97pzpjKVma8OkcrUc6WWIccZ48FlV21ZCeUFukthtqEDDEEw1CxEnwHgIydnynlwIDAQABo4HOMIHLMB0GA1UdDgQWBBQG+ykV13EVW9XxCTncLjLVYVX83TCBmwYDVR0jBIGTMIGQgBQG+ykV13EVW9XxCTncLjLVYVX83aFtpGswaTELMAkGA1UEBhMCUlUxDzANBgNVBAgTBk1vc2NvdzEPMA0GA1UEBxMGTW9zY293MQ8wDQYDVQQKEwZZYW5kZXgxDTALBgNVBAsTBFJvb3QxGDAWBgNVBAMTD3Jvb3QueWFuZGV4LmNvbYIJALEwbIlKhnreMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAmvNk8iAbV4+YMq/9oxkMeB6RxLs9m6jhYyAPuAI/dUhWSX+D+BnRcbsHWK4ra9G/riM1zerb5BD1apMz3faON2ydFJGB0thjlgr/KXfgaUXjp15QslEhsyhZIgEBTak+0BQkkh5+cFAvJhGCZqajr6m2I8Dix3mF3Ey7nSx1GDU=-----END CERTIFICATE-----

Запишем данные из задания в файлы ca.crt и ca.key соответственно. Теперь посмотрим на сертификат удостоверяющего центра: # openssl x509 -in ca.crt -noout -text Certificate: Data: Version: 3 (0×2) Serial Number: 12767824280512002782 (0xb1306c894a867ade) Signature Algorithm: sha1WithRSAEncryption Issuer: C=RU, ST=Moscow, L=Moscow, O=Yandex, OU=Root, CN=root.yandex.com Validity Not Before: Apr 6 16:43:09 2015 GMT Not After: Apr 5 16:43:09 2016 GMT Subject: C=RU, ST=Moscow, L=Moscow, O=Yandex, OU=Root, CN=root.yandex.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (1024 bit) Modulus: 00: a3:2b:01: a7:04:75:30:42: d4: f3:2d: be:6e:86: b8:7e:79:14:40:43:24:30:1b:30: a0: fa:7e:17:5b: 3b:7c:33: e8:97: fc: e1: b1: e1:00:86: e0:68: ca:86: 2f:4d: ab:38:66: e3:5f:80:8c: f0:79:72:77:54: dc: e7: b9:8f:52: eb:72: f5: af: c5: ed: a7: d7:91:46: ee: 13: d2:2c:6e:5d:1d: ef:7b: a7:3a:63:29:59:9a: f0: e9:1c: ad:47:3a:59:62:1c:71:9e:3c:16:55:76: d5: 90:9e:50:5b: a4: b6:1b:6a:10:30: c4:13:0d:42: c4: 49: f0:1e:02:32:76:7c: a7:97 Exponent: 65537 (0×10001) X509v3 extensions: X509v3 Subject Key Identifier: 06: FB:29:15: D7:71:15:5B: D5: F1:09:39: DC:2E:32: D5:61:55: FC: DD X509v3 Authority Key Identifier: keyid:06: FB:29:15: D7:71:15:5B: D5: F1:09:39: DC:2E:32: D5:61:55: FC: DD DirName:/C=RU/ST=Moscow/L=Moscow/O=Yandex/OU=Root/CN=root.yandex.com serial: B1:30:6C:89:4A:86:7A: DE

X509v3 Basic Constraints: CA: TRUE Signature Algorithm: sha1WithRSAEncryption 9a: f3:64: f2:20:1b:57:8f:98:32: af: fd: a3:19:0c:78:1e:91: c4: bb:3d:9b: a8: e1:63:20:0f: b8:02:3f:75:48:56:49:7f:83: f8:19: d1:71: bb:07:58: ae:2b:6b: d1: bf: ae:23:35: cd: ea: db: e4:10: f5:6a:93:33: dd: f6:8e:37:6c:9d:14:91:81: d2: d8:63: 96:0a: ff:29:77: e0:69:45: e3: a7:5e:50: b2:51:21: b3:28:59: 22:01:01:4d: a9:3e: d0:14:24:92:1e:7e:70:50:2f:26:11:82: 66: a6: a3: af: a9: b6:23: c0: e2: c7:79:85: dc:4c: bb:9d:2c:75: 18:35 Запросим новый сертификат с теми же значениями: # openssl req -out cert.csr -new -nodes

Country Name (2 letter code) [AU]: RU State or Province Name (full name) [Some-State]: Moscow Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Yandex Organizational Unit Name (eg, section) []: Root Common Name (e.g. server FQDN or YOUR name) []:10.0.0.15 Email Address []:

Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Подготовим структуру для работы удостоверяющего центра: # mkdir /etc/ssl/newcerts # echo 01 > /etc/ssl/serial # touch /etc/ssl/index.txt Следующая команда вернёт ошибку, текст которой не столь очевиден: # openssl ca -cert ca.crt -keyfile ca.key -in cert.csr -out cert.crt Using configuration from /etc/ssl/openssl.cnf Check that the request matches the signature Signature ok The stateOrProvinceName field needed to be the same in the CA certificate (Moscow) and the request (Moscow) На самом деле, проблема заключается в том, что строки в сертификатеудостоверяющего центра и запросе написаны в разных кодировках. Чтобы обойти эту проблему, следует отредактировать файл /etc/ssl/openssl.cnf и изменить значение параметра string_mask в секции [req] на pkix.Осталось подготовить файлы для веб-сервера:

# mv privkey.pem cert.key # cat ca.crt >> cert.crt Теперь установим веб-сервер (pacman -S nginx) и включим SSL в /etc/nginx/nginx.conf%, раскомментировав соответствующую секцию server{}.Проверяем:

# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful # systemctl restart nginx Но решение не принимается проверяющей системой с диагностикой «SSLv3 is weak». Изменим конфигурацию на рекомендуемую Mozilla: отметим опции Nginx и Modern, вставим конфигурацию в nginx.conf; сгенерируем параметры Диффи-Хеллмана: openssl dhparam -out dhparam.pem -outform PEM -2 2048; перезапустим nginx: systemctl restart nginx. 2.MariaDB repair В этом задании требуется восстановить работу базы данных. There is a MariaDB database in /var/lib/mysql. We had access there with login 'checker' and password 'masterkey', but something went wrong.

BTW, the `data` table structure was: ±------±--------±-----±----±--------±------+ | Field | Type | Null | Key | Default | Extra | ±------±--------±-----±----±--------±------+ | name | text | YES | | NULL | | | hits | int (11) | YES | | NULL | | | size | int (11) | YES | | NULL | | ±------±--------±-----±----±--------±------+ Из названия очевидно, что используется база данных MariaDB, известный форк MySQL.

Установим СУБД: pacman -S mariadb и попробуем запустить systemctl start mysqld. Из логов видно, что mysqld ищет файлы в неправильном месте. Из файла конфигурации /etc/mysql/my.cnf видно, что работа системы в сетевом режиме нарушена — добавлены параметры skip-networking, bind-address, указано неправильное значение datadir. Чтобы сэкономить время, не будем пытаться чинить файл конфигурации; вместо этого заменим его на заведомо рабочий:

[mysqld] key_buffer_size = 16M max_allowed_packet = 1M table_open_cache = 64 sort_buffer_size = 512K net_buffer_length = 8K read_buffer_size = 256K read_rnd_buffer_size = 512K myisam_sort_buffer_size = 8M tmpdir = '/var/tmp' Поправим владельца файлов — chown -R mysql: mysql /var/lib/mysql, и попробуем запустить базу данных ещё раз — systemctl restart mysqld.Ура, mysqld работает. Попробуем подключиться:

# mysql ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO) Видим, что установлена парольная защита, а пароль нам неизвестен/ Значит, как и в случае с операционной системой, придётся сбросить его: останавливаем mysqld: systemctl stop mysqld; подготавливаем файл с инструкцией сброса: echo «UPDATE mysql.user SET password = PASSWORD ('root') where user = 'root';» > /tmp/reset.sql; запускаем mysqld с загрузкой нашего файла: mysqld --user=mysql --init-file=/tmp/reset.sql; теперь остановим mysqld штатным образом, для этого следует нажать Ctrl-\; запустим unit снова — systemctl start mysqld После выполнения этой процедуры мы уже можем подключиться к базе данных с паролем root. Попробуем: mysql -ppassword -uroot. Из вывода команды show databases видим факт существования базы db, но в ней нет таблицы data. Однако же, эта таблица есть на диске (/var/lib/mysql/db/data.ibd). Не хватает table definition (data.frm).К счастью, задание содержит подсказку, как выглядит таблица, что позволяет реконструировать frm без анализа системных таблиц. Выполним запрос:

create table data2 (name text, hits int (11), size int (11)); Создать таблицу с именем data не получится, так как системные таблицы всё ещё содержат её упоминание. Теперь подключим файл данных к нашей новой таблице. Для этого отключим «пустой» ibd-файл от таблицы: alter table data2 discard tablespace;, подменим его заполненным mv data.ibd data2.ibd и подключим обратно alter table data2 import tablespace;.Так как db.data до сих пор числится в системных таблицах, то drop table db.data мы сделать не сможем. Придётся создать временную базу данных, перенести в неё новую таблицу, удалить старую, а затем создать заново:

rename table db.data2 to db2.data; drop database db; create database db character set utf8; rename table db2.data to db.data; alter table db.data engine = innodb; Осталось лишь выдать доступ пользователю: grant all privileges on db.* to 'checker'@'%' identified by 'masterkey';. К сожалению, проверка так и не проходит из-за ошибки подключения. Проверка с помощью tcpdump показывает, что mysqld не отвечает. Проверим фаервол с помощью iptables-save и обнаружим проблему, оставленную злодеем, — в таблицу nat добавлены ошибочные правила. Однако, их удаление ненадолго восстанавливает работу сети — правила появляются снова.Как правило, периодические действия вызваны работой crontab. Проверим (crontab -l, cat /etc/cron.* /etc/crontab /etc/cron.d/*) и удалим все задания текущего пользователя (crontab -r).

3.Binary Run 1.exe

В данном задании нужно запустить «необычную» программу. Из задания нам известно имя файла — »1.exe». Найдём файл на файловой системе и проверим его содержимое:

# find / -iname 1.exe /root/1/1.exe # file /root/1/1.exe /root/1/1.exe: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows Для запуска .NET-приложений под GNU/Linux существует среда mono. Установим её (pacman -S mono) и попробуем запустить нашу программу: # cd /root/1 # mono 1.exe Но это задание не такое простое, как кажется. В ответ, game вернёт: Name: Binary Status: uncompleted Output: bad program Попробуем понять, что же делает программа 1.exe. Запуск mono под strace покажет, что программа слушает TCP-сокет и выполняет команды, переданные проверкой. Поверхностный анализ трафика с помощью tcpdump показывает, что программа умеет читать файлы, обращаться к встроенной базе данных и выполнять вычисления. Проверка заканчивает работу после выполнения вычислений, значит, проблема скорее всего заключается в них.Часто можно извлечь дополнительную информацию, поискав текстовые строки внутри исполняемых файлов. Попробуем воспользоваться этим приёмом — установим пакет программ binutils и применим программу strings на файл 1.exe. Один фрагмент вывода похож на список библиотек, используемых программой:

System.Core mscorlib System.Xml dnAnalytics Все эти библиотеки, кроме dnAnalytics, входят в состав mono — это несложно проверить с помощью пакетного менеджера (pacman -Ql mono).4.Mongo В этом задании нужно развернуть шардированное хранилище MongoDB, записав в него данные, предложенные организаторами. There is a database in /var/lib/db.tar.gz.

Make a root.features collection with 2 shards and make it available on the standard port.

Для начала установим mongodb: pacman -S mongodb. Организаторы оставили архив с базой, распакуем его и сделаем архивную копию: cd /var/lib/mongodb tar jxf /var/lib/db.tar.bz2 mongod --dbpath db mongodump rm -rf db Для шардирования понадобится специальная служебная база, называемая configdb. Создадим её: mkdir -p /data/configdb mongod --configsvr & Теперь запустим «шардировщик» mongos: mongos --configdb localhost &. В задании требуется поднять два шарда, поэтому подготовим два экземпляра mongod: mkdir /var/lib/mongodb/s1 /var/lib/mongodb/s2 mongod --dbpath /var/lib/mongodb/s1 --port 30001 --nojournal & mongod --dbpath /var/lib/mongodb/s1 --port 30002 --nojournal & И подключим их к mongos: # mongo mongos> sh.addShard («localhost:30001») mongos> sh.addShard («localhost:30002») mongos> sh.enableSharding («root») Теперь осталось загрузить дамп обратно: mognorestore --port 30001 dump/.Однако этого недостаточно для решения задачи — коллекция root.features не будет равномерно расшардирована между двумя шардами. Решим эту проблему, создав индекс по идентификатору документа и включив балансировщик:

# mongo root mongos> db.features.ensureIndex ({»_id»: «hashed»}) mongos> sh.shardCollection («root.features», {»_id»: «hashed»}) mongos> sh.enableBalancing («root.features») Подождав, пока коллекция перераспределится между шардами, запустим проверку повторно.5.Strange Protocol Это задание оказалось самым сложным. Собственно, как мы и сами предсказывали. Set up an echo server on port 13000.

На этот раз нам нужно запустить эхо-сервер на порту 13000.Это задание кажется простым — действительно, простейшая реализация эхо-сервера уже встроена, например, в xinetd. Запуск tcpdump port 13000 показывает, что обмен происходит по протоколу UDP, но настройка echo-dgram в xinetd не даёт ожидаемого результата.

Посмотрим на трафик внимательнее — снова запустим tcpdump, но уже с параметром -X. Последний пакет кажется интересным:

0×0010: 0a00 000f ebee 32c8 0012 ffd6 656e 6574 …2…enet 0×0020: 2065 7272 6f72 .error Поиск по слову enet приводит к сайту, описывающему реализацию протокола enet, который позволяет передавать потоки данных через UDP, не заботясь о потере пакетов (как в TCP).Дальнейший поиск приводит к библиотеке pyenet, привязке к enet для языка Python, который как раз подойдёт для нашей задачи. Напишем несложную программу:

import enet import sys

host = enet.Host (enet.Address (b'0.0.0.0', 13000), 100, 0, 0)

while True: evt = host.service (0) if evt.type == enet.EVENT_TYPE_RECEIVE: data = evt.packet.data evt.peer.send (0, enet.Packet (data)) Осталось установить эти библиотеки: pacman -S git git clone git://github.com/aresch/pyenet cd pyenet git clone git://github.com/lsalzman/enet pacman -S cython base-devel python setup.py build python setup.py install Запускаем нашу программу, и проверка на этот раз выполняется успешно.6.File Организаторы спрятали root.txt где-то внутри /root/file. There is a /root/file inside your image. Find a good root.txt file and make it available via image_ip/root.txt.

Попробуем понять, чем же является /root/file: # file /root/file /root/file: LVM2 PV (Linux Logical Volume Manager), UUID: XT6zLL-YAUv-nmA9-BSrw-2pBV-CTi2-vqKe35, size: 31457280 Похоже на образ диска. В Linux есть модуль ядра loop, который позволяет превращать файлы в блочные устройства. Воспользуемся им: losetup /dev/loop0 /root/file Так как внутри образа диска находится том LVM, подключим его штатными средствами: # vgchange -ay 1 logical volume (s) in volume group «VolGroup00» now active Посмотрим, что внутри: mount /dev/mapper/VolGroup00-lv0 /mnt ls /mnt Видим root.txt.gz, распаковываем: gunzip /mnt/root.txt.gz.Так как мы уже установили nginx для задания SSL, воспользуемся им для раздачи файла по HTTP:

umount /mnt mount /dev/mapper/VolGroup00-lv0 /usr/share/nginx/html/ К сожалению, проверка не проходит — мы нашли не тот root.txt. Будем смотреть дальше. Посмотрим, какая у нас файловая система: # file -s /dev/dm-0 /dev/dm-0: BTRFS Filesystem sectorsize 4096, nodesize 4096, leafsize 4096) Поскольку в btrfs есть понятние subvolume, посмотрим на их список: # pacman -S btrfs-progs # btrfs subvolume list /usr/share/nginx/html/ ID 256 gen 14 top level 5 path root ID 257 gen 11 top level 5 path root_1 Оказывается, есть ещё один subvolume — root_1. Смонтируем именно его: umount /usr/share/nginx/html mount -t btrfs -o subvol=root_1 /dev/mapper/VolGroup00-lv0 /usr/share/nginx/html/ Теперь мы нашли другой файл root.txt.gz. Распакуем его: gunzip/usr/share/nginx/html/root.txt.gz.Это и будет решением задачи.

7.MariaDB Tuning Во время решения задачи MariaDB repair мы починили базу данных, но она работает слишком медленно. Настало время исправить это. The repaired MariaDB is slow. Tune it up.

Посмотрим, где тормозит наша база. Включим slow query log, куда будут попадать все запросы, выполняющиеся дольше секунды: mysql -u root -ppassword db mysql> set global slow_query_log = ON; mysql> set global long_query_time = 1; Запускаем проверку и смотрим в лог: tail /var/lib/mysql/shannon-slow.log.Видим запрос SELECT COUNT (*) FROM db.data WHERE size < 10;.

Посмотрим на план запроса:

mysql> explain SELECT COUNT (*) FROM db.data WHERE size < 10 \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: data type: ALL possible_keys: NULL key: NULL key_len: NULL ref: NULL rows: 25061163 Extra: Using where 1 row in set (0.00 sec) Конечно же, такой запрос выполяется слишком медленно — у нас нет индексов для этого поля. Добавим индекс: mysql> create index data_size on data (size);.Повторный запуск проверки покажет нам ту же проблему для data (hits), которую мы решаем аналогичным образом.

8.HG В /root/repo лежит mercurial репозиторий, для которого нам надо поправить историю и сделать его доступным через http. There is a HG repository in /root/repo.

Drop all .gz files in all revisions and make it available via ip:8000/

Первым делом, установим mercurial: pacman -S mercurial. Изменить историю можно с помощью модуля convert, который по умолчанию отключён. Включим его: # cat < ~/.hgrc [extensions] hgext.convert= EOF Этот модуль умеет применять правила сопоставления файлов в исходном и целевом репозитории. Такие правила называются filemap. Напишем и применим правило, которое выкинет файл 2.osm.gz: echo 'exclude »2.osm.gz»' > /root/fmap hg convert --filemap ~/fmap /root/repo /root/repo1 После выполнения команды, получим репозиторий /root/repo1, который лишён файла 2.osm.gz во всех ревизиях. Осталось сделать его доступным снаружи. В mercurial есть встроенный веб-сервер, которым мы и воспользуемся: cd /root/repo1 hg serve 9.Strange File С этим заданием справилось самое большое количество команд — 151. На файловой системе находится странный файл tester/file, который никто не может изменить. We got a strange file in ~tester/file. No one can change it. Fix it.

И действительно, файл изменить не получается — даже из-под рута: # echo test >> ~tester/file -bash: /home/tester/file: Permission denied Для начала посмотрим, что у нас за файловая система такая: # mount | grep ' on / ' /dev/sda2 on / type ext4 (rw, relatime, data=ordered) Из руководства по ext4 (man 5 ext4) можно узнать, что файлы на этой ФС могут иметьследующие атрибуты: FILE ATTRIBUTES The ext2, ext3, and ext4 filesystems support setting the following file attributes onLinux systems using the chattr (1) utility: a — append only

A — no atime updates

d — no dump

D — synchronous directory updates

i — immutable

S — synchronous updates

u — undeletable

In addition, the ext3 and ext4 filesystems support the following flag:

j — data journaling

Finally, the ext4 filesystem also supports the following flag:

e — extents format

For descriptions of these attribute flags, please refer to the chattr (1) man page.

Посмотрим на страницу chattr (1), где подробно описывается поведение системы для файлов с установленым атрибутом immutable: ATTRIBUTES A file with the 'i' attribute cannot be modified: it cannot be deleted or renamed, no link can be created to this file and no data can be written to the file. Only the supe‐ruser or a process possessing the CAP_LINUX_IMMUTABLE capability can set or clear this attribute.

Ответ очевиден — нужно снять этот атрибут с файла: chattr -i ~tester/file. Задача решена.

© Habrahabr.ru