понедельник, 31 июля 2023 г.

How to cleanup wsl's disk

На офисном компе винда сказала, что место кончилось (475 ГБ).
Оказалось, всё съел WSL.

Очищается следующей последовательностью действий в терминале:

wsl --shutdown
diskpart
# open window Diskpart
select vdisk file="C:\WSL-Distros\…\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit


Source: https://github.com/microsoft/WSL/issues/4699#issuecomment-627133168

среда, 10 мая 2023 г.

How to build and install the kernel

 Sources:

  • https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel#apt-get
  • https://www.maketecheasier.com/build-custom-kernel-ubuntu/
  • https://stackoverflow.com/a/75622441


The algorithm:

  1. Make source directory (I have named it 'lab') and go there: `mkdir ~/lab; cd ~/lab` 
  2. Download linux sources of your distributes: `apt-get source linux-image-unsigned-$(uname -r)`
  3. Download linux sources from git repository: `git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git`
  4. Go to the Linus' source directory: `cd ~/lab/linux`
  5. Copy your distribution's config: `cp /boot/config-$(uname -r) .config`
  6. Apply the config: `make olddefconfig`
  7. Copy a directory of your distribution's source in order to sign your build: `cp -avr ~/lab/linux-hwe-5.15-5.15.0/debian ~/lab/linux/debian`
  8. Build the kernel: `make clean && make -j8`
  9. Build deb-package: `make deb-pkg LOCALVERSION=-custom`
  10. Install deb-packages: `sudo dpkg -i ~/lab/linux-*.deb`
  11. Reboot your system with a new kernel =)

вторник, 22 февраля 2022 г.

zettelup

 Для облегчения работы с цеттелем с учётом моего тулчейна

(git & Obsidian) написал скрипт `zettleup`, который использую

на телефоне, Linux-е на Винде.


Скрипт на телефоне (Android через Termux)

```

#!/bin/bash

curdir=$(pwd)

cd /storage/E6E0-1F04/zettel # an external SD card

git add . # add any new notes recursively

git commit -am "up" # message doesn't matter for Zettel

git pull

git push

cd ${curdir}

```


В Linux-е скрипт такой-же, меняется только путь к папке репозитория.


Скрипт для винды (zettelup.bat).

```

current_dir="%CD%"

cd "%USERPROFILE%\workspace\zettel"

git add .

git commit -am "up"

git pull

git push

cd "%current_dir%"

```


Скрипт кладём в директорю, которая находится в списке в переменной среды `PATH` (в винде добавлял в PATH новую директорию, т.к. системные трогать не хотел).


Перед "работой" с цеттелем и после неё запускаю `zettelup` (в винде через `Win+R` и прям в строке запуска пишу `zettelup`, на телефоне запускаю Termux и запускаю скрипт в нём, на Linux-е через `Alt+F2`). Даже если ничего нового не писал нигде, это уже как привычка и занимает пару секунд.


Примечание: именнно `zettelup` указанными способами набираю редко. Обычно просто стрелкой вверх выбираю как одну из 3-х последних набранных комманд. Так что получается вполне удобно.

вторник, 27 июля 2021 г.

Reverse Engineering шпаргалка.

 Сразу скажу, тут я нуб! Это шпаргалка для меня (как я решил задачу). Ну может кому ещё будет полезна. Данные черпал из Reverse Engineering for Beginners (berkeley.edu)

Вводная:

    По работе нужно было исправить логику 3rdparty библиотек, которые предоставил заказчик с хидерами и сборками как static lib в дебажном и релизном варианте. Так как были дебажные версии то решил, что RE будет не сложным. Так и получилось.

Шпаргалка:

1. Получаем asm листнинг библиотеки через утилиту dumpbin, которая идёт в составе Visual Studio.

2. В asm листинге ищем функцию, которую надо "расшифровать" простым поиском по тексту.

3. Для анманглинга имён функций используем утилиту undname из состава Visual Studio.

4. Читаем и пишем свой вариант функции (допустим на С++).

5. Пишем тест на расшифрованную логику.

6. Прогоняем через тест свою функцию и функцию из препарируемой библиотеке.


Детали.


Дело было в винде и я использовал Notepad++. Сделал вертикальный разрез. Справа был чистый asm-листинг - слева был "рабочий" файл, в котором я писал комментарии при расшифровке.


На картинке мои комментарии зелёным.
В процессе расшифровки в комментариях переменные обычно называл так, что бы по asm листингу было проще отследить. Например на скриншоте  по адресу [ebp-24h] находится адрес std::vector< uint8_t >. В комментариях я так и назвал переменную - ebp_24. Все переменные ebp-X - это локальные переменные функции.  ebp-0h - это адрес нашей функции, в которой мы "находимся". Если функция возвращает значение, то выше 0 в стеке лежит (в случае x86) адрес возвращаемой переменной. Дальше ( ebp+X ) лежат входные параметры функции. Указатели (в этом случае) занимают 8 байт, простые значения (uint8_t, uint32_t) - 4 байта или больше (double, int64_t - 8 байт). Про остальные не скажу, но это легко вычисляется при анализе.

Затем написал функцию и к ней написал тест.

На скриншоте слева код теста, а справа код, который я "родил" в процессе расшифровки. Тест пассится, но с кодом надо ещё разобраться (непонятные магические цифры - надо поглядеть предметную область и понять зачем, может в исходном коде ошибка). AfdxPack::GetIpPack - это препарируемая функция, а AfdxPack2::GetIpPack - это то, что я "родил". Как всегда, тест сильно снижает вероятность ошибки при дешифровке.


среда, 26 мая 2021 г.

GitSvn - ошибка fatal: bad object


 При обновлении данных из SVN репозитория заказчика через `git svn fetch` получил следующую ошибку:

W: -empty_dir: branch/MC21FMSINT-583/OHBS/OHBSioGUI/MainForm.resx
Checking svn:mergeinfo changes since r2852: 13 sources, 3 changed
fatal: bad object a3e4f2cbe92958764e31197c3391fe7eccc33f88
rev-list -1 46d79549314a6c8bfd87ce1d50ab15db8992c326
a3e4f2cbe92958764e31197c3391fe7eccc33f88 --not b93da3edf57134b3bd9722ec875219d9ac67c166: command returned error: 128

В поисках решения наткнулся на заметку: Alieniloquent: "git svn fetch dies with \"fatal: bad object\""

Шпаргалка для решения:

  1. Заходим в директорию .git
  2. Запускаем поиск упоминаний о проблемном коммите (в моём случае a3e4f2cbe92958764e31197c3391fe7eccc33f88)
  3. Удаляем бинарные файлы, которые относятся к мержу и черри-пику.
  4. Ещё раз запускаем `git svn fetch`
В моём случае выглядело так (через GitBash в Windows):

rgade@DESKTOP-TFEG50M MINGW64 ~/workspace/myproject/.git (GIT_DIR!)
$ find . -exec grep -Hin a3e4f2cbe92958764e31197c3391fe7eccc33f88 {} \; | grep "Binary file"
Binary file ./svn/.caches/check_cherry_pick2.db matches
Binary file ./svn/.caches/lookup_svn_merge.db matches

rgade@DESKTOP-TFEG50M MINGW64 ~/workspace/myproject/.git (GIT_DIR!)
$ rm ./svn/.caches/check_cherry_pick2.db

rgade@DESKTOP-TFEG50M MINGW64 ~/workspace/myproject/.git (GIT_DIR!)
$ rm ./svn/.caches/lookup_svn_merge.db

воскресенье, 23 мая 2021 г.

Работа с SVN репозиторием через git-svn

Речь не о переносе проекта с SVN на GIT, а про работу с SVN репозиторием через git-svn.

Ситуация: у заказчика SVN репозиторий. Помимо прочего он ещё и в приватном VPN (Checkpoint VPN, по факту не получилось подключиться к нему из Линукса через `snx`, пришлось подключаться из Windows). 
Что бы дальше так не мучиться, решил работать через `git-svn`. Наступил на пару граблей. Ниже шпаргалка как работать в таких случаях.

Зачем?


1) При работе с git-svn не нужен постоянный коннект к репозиторию заказчика.
2) Простота создания веток для проверок различных вариантов решения проблемы.

Важно

Вне зависимости от того, в какой git-ветке мы находимся, при вызове git svn dcommit изменения будут заливаться в SVN ветку, на которую мы "настроены" во внешнем SVN репозитории. Я, по ошибке, залил не отревьювленные коммиты в транк, хотя был в другой ветке. Потому и решил эту шпаргалку написать.

Посмотреть, на какую ветку в SVN репозитории сейчас настроены

git svn dcommit -n или git svn dcommit --dry-run. Без реального пуша коммита покажет в какую ветку в SVN репозитории будет заливать данные при вызове git svn dcommit.

Альтернативный вариант.

git svn info

Смотреть поле URL. Например:

$ git svn info
Path: .
URL: http://customer/svn/projectX/trunk
Repository Root: http://customer/svn/projectX
Repository UUID: 10230cbc-1c0b-47a3-9371-a2b47a5679dc
Revision: 843
Node Kind: directory
Schedule: normal
Last Changed Author: Rinat.Gadelshin
Last Changed Rev: 843
Last Changed Date: 2021-05-23 19:32:30 +0300 (Sun, 23 May 2021)

Мы находимся в транке.

Создать новую ветку в SVN репозитории

git svn branch <new_branch_name>

Примечание: после создания новой ветки в SVN репозитории мы не переключились на неё, а остались в настроены на предыдущую SVN ветку. В данном случае на trunk.

Пример создания SVN ветки OHBS-29-3 и переключения Git репозитория на неё. С демонстрацией того, что автоматом не перенастраивается после создания:

$ git svn branch OHBS-29-3
Copying http://customer/svn/projectX/trunk at r843 to http://customer/svn/projectX/branch/OHBS-29-3...
Found possible branch point: http://
customer/svn/projectX/trunk => http://customer/svn/projectX/branch/OHBS-29-3, 843
Found branch parent: (refs/remotes/OHBS-29-3) 762910dc607920a9b59d0b5809102e03c19bc7cd
Following parent with do_switch
Successfully followed parent
r845 = c55b0f28e08d0a6db8c06230e0f620e40832a175 (refs/remotes/OHBS-29-3)
$ git svn info
Path: .
URL: http://customer/svn/projectX/trunk
Repository Root: http://
customer/svn/projectX
Repository UUID: 10230cbc-1c0b-47a3-9371-a2b47a5679dc
Revision: 843
Node Kind: directory
Schedule: normal
Last Changed Author: Rinat.Gadelshin
Last Changed Rev: 843
Last Changed Date: 2021-05-23 19:32:30 +0300 (Sun, 23 May 2021)
$ git reset OHBS-29-3
HEAD is now at c55b0f28e Create branch OHBS-29-3
$ git svn info
Path: .
URL: http://customer/svn/projectX/branch/OHBS-29-3
Repository Root: http://
customer/svn/projectX
Repository UUID: 10230cbc-1c0b-47a3-9371-a2b47a5679dc
Revision: 845
Node Kind: directory
Schedule: normal
Last Changed Author: Rinat.Gadelshin
Last Changed Rev: 843
Last Changed Date: 2021-05-23 19:32:30 +0300 (Sun, 23 May 2021)


Переключиться на другую ветку в SVN репозитории

git reset <branchname>

<branchname> это то, что идёт после remotes/ в выводе `git branch -a`.

Примечание: trunk отображается как remotes/origin/trunk.

Пример переключения на ветку tftp_refactoring и обратно на trunk:

$ git reset tftp_refactoring
$ git reset origin/trunk

Удалить ветку в SVN репозитории

Удалить ветку в SVN репозитории средствами git-svn нельзя (на момент версии 2.31.1). Удалять ветку необходимо средствами Subversion.

Либо через svn rm <full_path_to_branch_folder_on_the_repo
Либо через TortoiseSVN (в винде).

После того, как ветка удалена в SVN репозитории, git svn всё равно её отображает.

Для того, что бы удалить её из Git репозитория, необходимо:

1.  git update-ref -d remotes/<branchname>
2. git gc --prune=now 

Например, что бы удалить упоминания о ветке OHBS-29 надо выполнить:

git update-ref -d remotes/OHBS-29 && git gc --prune=now


пятница, 24 января 2020 г.

Проблемы с OOM Killer-ом

Шпаргалка

Следующие действия надо выполнять из под пользователя root.

Что бы примелось "сейчас" без перезагрузки:

echo 2 > /proc/sys/vm/overcommit_memory
echo 80 > /proc/sys/vm/overcommit_ratio

Что бы сохранилось после перезагрузки нужно в файл /etc/sysctl.conf дописать (если их там нет) следующие строчки

vm.overcommit_memory = 2
vm.overcommit_ratio = 80
 

Суть проблемы

По умолчанию в Linux ядро всегда "удовлетворяет" запрос на выделение памяти, даже если этой памяти нет. Суть стратегии в том, что программы не всегда используют всю запрашиваемую память, или используют её не сразу, и к тому моменту когда она будет нужна программе, она скорее всего будет доступна. Можно корректировать это поведение через vm.overcommit_memory. Значение 2 для этого аргумента говорит, что если нет "доступной виртуальной" памяти, то вызов malloc() (запрос на выделение памяти в приложении) должен возвращать NULL (честно говорит программе, что памяти которую ей надо в доступе нет.

Второй параметр vm.overcommit_ration определяет, какой процент физической памяти (RAM) + плюс добавленный к ней swap рассматривать, для определения доступного для выделения пространства. Т.е. мы указали, что можно выделять память в 80% процентах RAM + swap. Т.е. на машине с 4GB RAM и 1GB swap для приложений доступно 4.2 ГБ (3.2GB от RAM и 1GB от swap). Если в пределах этого размера нет непрерывного (!!!) свободного пространства, то будет вернут NULL.

Источники:

  • https://www.kernel.org/doc/Documentation/sysctl/vm.txt
  • https://www.win.tue.nl/~aeb/linux/lk/lk-9.html#ss9.6
  • http://bl0rg.krunch.be/oom-frag.html 
  • https://utcc.utoronto.ca/~cks/space/blog/linux/DecodingPageAllocFailures

пятница, 7 сентября 2018 г.

Модифицикация стороннего rpm-пакета

Шпаргалка


  1. Исходная версия модифицируемого пакета установлена.
  2. Кладём файлы (если требуется добавить файлы) в необходимые места на своей системе.
  3. Вызываем rpmrebuild -e <package-name> 
  4. В vi-редакторе модифицируем spec-файл и сохрняем (:wq)
  5. Забираем пересобранный пакет из ~/rpmbuild/RPMS/<arch>/<package>

История


Потребовалось собрать Qt5 SQL драйвер для Oracle Database в виде отдельного пакета для Oracle Linux 7. По аналогии с имеющимися в public репозитории аналогичными пакетами аналогичных драйверов для других баз данных. Для сборки были скачаны rpm-ки oracle-instantclient18.3 c оффициального сайта и требуемый драйвер был собран. Все эти рпм-ки были помещены в локальный репозиторий. Но при запуске

sudo yum  install qt5-qtbase-oci

yum ругался следующим образом:


[grin@grinol7 ~]$ sudo yum install qt5-qtbase-oci
Loaded plugins: langpacks, ulninfo
Resolving Dependencies
--> Running transaction check
---> Package qt5-qtbase-oci.x86_64 0:5.9.2-3el7 will be installed
--> Processing Dependency: libclntsh.so.18.1()(64bit) for package: qt5-qtbase-oci-5.9.2-3el7.x86_64
--> Finished Dependency Resolution
Error: Package: qt5-qtbase-oci-5.9.2-3el7.x86_64 (topaz)
           Requires: libclntsh.so.18.1()(64bit)
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest


Проверка показала, что требуемая библиотека находится (как сам файл так и Provides запись к нему) в пакете oracle-instantclient18.3-basic.

[grin@grinol7 tmp]$ rpm -ql oracle-instantclient18.3-basic
/usr/lib/oracle/18.3/client64/bin/adrci
/usr/lib/oracle/18.3/client64/bin/genezi
/usr/lib/oracle/18.3/client64/lib/libclntsh.so.18.1
/usr/lib/oracle/18.3/client64/lib/libclntshcore.so.18.1
/usr/lib/oracle/18.3/client64/lib/libipc1.so
/usr/lib/oracle/18.3/client64/lib/libmql1.so
/usr/lib/oracle/18.3/client64/lib/libnnz18.so
/usr/lib/oracle/18.3/client64/lib/libocci.so.18.1
/usr/lib/oracle/18.3/client64/lib/libociei.so
/usr/lib/oracle/18.3/client64/lib/libocijdbc18.so
/usr/lib/oracle/18.3/client64/lib/libons.so
/usr/lib/oracle/18.3/client64/lib/liboramysql18.so
/usr/lib/oracle/18.3/client64/lib/network/admin/README
/usr/lib/oracle/18.3/client64/lib/ojdbc8.jar
/usr/lib/oracle/18.3/client64/lib/xstreams.jar
/usr/share/oracle/18.3/client64/doc/BASIC_README
[grin@grinol7 tmp]$ rpm -q --provides oracle-instantclient18.3-basic

libclntsh.so.18.1
oracle-instantclient18.3-basic = 18.3.0.0.0-1
oracle-instantclient18.3-basic(x86-64) = 18.3.0.0.0-1


Но если вчитаться в лог об ошибке, то qt5-qtbase-oci требует не просто libclntsh.so.18.1, а libclntsh.so.18.1()(64bit). Также видно, что oracle-instantclient18.3 в качестве "provides" дважды указывает сам себя, причём второй раз дополнительно в скобках пишет архитектуру.

oracle-instantclient18.3-basic = 18.3.0.0.0-1
oracle-instantclient18.3-basic(x86-64) = 18.3.0.0.0-1


Следовательно нужно пересобрать oracle-instantclient18.3-basic, с добавленной в spec-file "Provides" записью для libclntsh.so.18.1()(64bit).

Помимо этого можно добавить файл конфигурации для ld (например в моём случае /etc/ld.so.conf.d/oracle-instantclient18.3.conf).

Редактировать (пересобирать новую rpm) будем через утилиту rpmrebuild.
Предварительно создадим файл в своей файловой системе /etc/ld.so.conf.d/oracle-instantclient18.3.conf, в который запишем путь к библиотекам oracle

/usr/lib/oracle/18.3/client64/lib

Напоминаю,  что в моём случае oracle-instantclient18.3-basic уже был установлен. Далее выполняем команду

rpmrebuild -e oracle-instantclient18.3-basic

После этого в терминале откроется vi редактор spec-файла для нового пакета.

В моём случае необходимо было добавить строку 

Provides:      libclntsh.so.18.1()(64bit)
 

и строку

%attr(0644, root, root) "/etc/ld.so.conf.d/oracle-instantclient-18.3.conf"

в соответствующие им места spec-файла.
После этого закрываем редактор с сохранением изменений (:wq).
Возвращаемся в терминал, где на запрос rmprebuild

Do you want to continue ? (y/N) 

отвечаем утвердительно.

В моём случае новый пакет  был собран в течении секунд 20-ти (т.е. не сразу - у кого-то быстрее, у кого-то дольше). Если ошибок не пишет - то значит всё ок, просто работает. В конце rpmbuild уведомляет что пакет создан и указывает где:

result: /home/grin/rpmbuild/RPMS/x86_64/oracle-instantclient18.3-basic-18.3.0.0.0-1.x86_64.rpm
Дальше я положил пакет  в свой локальный репозиторий (выполнил createrepo на сервере где расположен репозитори) и переустановил его

sudo yum clean expire-cache
sudo yum reinstall oracle-instantclient18.3-basic

После этого qt5-qtbase-oci успешно установился.

вторник, 30 января 2018 г.

Памятка: замена одного RPM пакета, другим в одной операции

Суть:
    Требуется использовать (в Red Hat based линуксах) команду yum shell
  • yum shell
  • remove <old_package>
  • install <new_package>
  • run
  • ....
  • exit

 Предистория
     Требовалось установить свою реализацию NTP-сервера/клиента вместо стандартного для Oracle Linux пакета ntp. В своём пакете (tssd) прописано, что он предоставляет функционал ntp (Provides: ntp внутри spec-файла). Помимо этого указано, что он конфликтует с ntp (что бы они сразу хором время не подводили). Итого: если попытаться установить сначала tssd - то получим конфликт, что сначала надо удалить ntp. Если сначала удалить ntp - то  зависимые от него системные пакеты тоже удалятся, а они могут быть важны и удалять их не стоит.

Пример выполнения
   Ниже приведён лог замены ntp на tssd.

[root@grinVMOL6x86 ~]# yum shell
Loaded plugins: security
Setting up Yum Shell
> remove ntp
Setting up Remove Process
> install tssd
Setting up Install Process
> run
--> Running transaction check
---> Package ntp.i686 0:4.2.6p5-12.0.1.el6_9.2 will be erased
---> Package tssd.i686 0:1.4-75 will be installed
--> Finished Dependency Resolution

================================================================
 Package Arch  Version                 Repository          Size
================================================================
Installing:
 tssd    i686  1.4-75                  topaz               118 k
Removing:
 ntp     i686  4.2.6p5-12.0.1.el6_9.2  @public_ol6_latest  1.6 M

Transaction Summary
================================================================
Install       1 Package(s)
Remove        1 Package(s)

Total download size: 118 k
Is this ok [y/N]: y
Downloading Packages:
tssd-1.4-75.i686.rpm                                                                                                                                                                                            | 118 kB     00:00     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : tssd-1.4-75.i686                              1/2 
tssd start/running, process 7303
  Erasing    : ntp-4.2.6p5-12.0.1.el6_9.2.i686               2/2 
  Verifying  : tssd-1.4-75.i686                              1/2 
  Verifying  : ntp-4.2.6p5-12.0.1.el6_9.2.i686               2/2 

Removed:
  ntp.i686 0:4.2.6p5-12.0.1.el6_9.2                                                                                                                                                                                                    

Installed:
  tssd.i686 0:1.4-75                                                                                                                                                                                                                   

Finished Transaction
> exit
Leaving Shell
[root@grinVMOL6x86 ~]#

среда, 17 января 2018 г.

Памятка: конвертация исходников CP-1251 в UTF-8 (Linux)

В долгоживущем проекте, который уже перенесли на линукс малая часть исходников была в кодировке CP-1251 (Windows 1251). А основная часть в кодировке UTF-8. Требовалось без затей перекодировать в UTF-8 указанную малую часть.

Выполнили следующим скриптом:

for incorrect_file in $(for file in $(find $(pwd) -type f | grep -E "*\.h$|*\.c$|*\.hpp$|*\.cpp$"); do file -i ${file}; done | grep charset=iso-8859-1 | awk 'BEGIN{FS=":"}{print $1}'); do echo ${incorrect_file}; iconv -f cp1251 -t utf-8 ${incorrect_file} -o ${incorrect_file}; done

Более читаемая форма:

files=$(find $(pwd) -type f | grep -E "*\.h$|*\.c$|*\.hpp$|*\.cpp$"); \
incorrect_files=$( for_ file in ${files}; do \
                                  file -i ${_file}; \
                              done | \
                              grep charset=iso-8859-1 | \
                              awk 'BEGIN{FS=":"}{print $1}'); \
for incorrect_file in ${incorrect_files} do \
    echo ${incorrect_file}; \
    iconv -f cp1251 -t utf-8 ${incorrect_file} -o ${incorrect_file}; \
done

Разбор:
  • find $(pwd) -type f - ищет рекурсивно все файлы вглубь относительно текущей директории
  • grep -E "\.h$|\.c$|\.hpp$|.\cpp$" - фильтр - выводит в stdout только файлы с раширениями: .h .c .hpp .cpp
  • file -i ${file} - выдаёт информацию о файле, включая его кодировку
  • grep charset=iso-8859-1 - фильтр - выводит в stdout только информацию по файлам, имеющим указанную кодировку. Суть в том, что для файла с фактической кодировкой CP1251 команда file  -i выводит информацию, что кодировка iso-8859-1.
  • awk 'BEGIN {FS=":"}{print $1}' из отфильтрованной строки команды file -i выводит только имя файла.
  • iconv -f cp1251 -t utf-8 ${incorrect_file} -o ${incorrect_file} - собственно перекодирует файл из кодировки CP1251 в UTF-8.

вторник, 26 декабря 2017 г.

Памятка: Скачивание rpm-пакета со всеми зависимостями

Периодически заказчику на объект, на котором не доступа к интернету (соотвественно и к паблик репозиториям), требуется поставить ПО (в виде RPM-пакета) вместе со всеми пакетами, от которых он зависит.

В Oracle Linux (6/7) это можно сделать через yum.

1. Создаём папку, куда будем скачивать пакеты:
     mkdir ~/tmp/rpms
2. Переходим в эту папку:
      cd ~/tmp/rpms
3. Скачиваем (через sudo или из-под рута):
    sudo yum install \
    --installroot=$(pwd) \
    --downloadonly \
    --downloaddir=$(pwd) <packet-name>
4. Удаляем папку var (может увеличить размер результата то гигабайта, вместо требуемых 122 МБ - был прицендент):
    rm -rf $(pwd)/var

Пример для скачивания  пакета net-snmp-utils

[grin@grintop]$ mkdir ~/tmp/rpms
[grin@grintop]$ cd ~/tmp/rpms
[grin@grintop]$ sudo yum install --installroot=$(pwd) --downloadonly --downloaddir=$(pwd) net-snmp-utils
[grin@grintop]$ rm -rf var

четверг, 14 декабря 2017 г.

Памятка: удаление подмодулей в Git

Взято отсюда: https://gist.github.com/kyleturner/1563153

1. В файле .gitmodules удаляем строки, относящиеся к удаляемому подмодулю
2. В файле .git/config удаляем строки, относящиеся к удаляемому подмодулю
3. Выполняем команду: git rm --cached <path_to_submodule>
4. Удаляем папку, куда примонтирован подмодуль.
5. Коммитим изменения.

вторник, 20 декабря 2016 г.

Шпаргалка по rpmbuild

Пересборка src.rpm:

    rpmbuild --rebuild xxx.src.rpm

Распковка src.rpm:

    rpm2cpio xxx.src.rpm | cpio --extract --make-directories --verbose

Частичная сборка:

    rpmbuild --short-circuit -b<id> --target $(uname -m) ~/rpmbuild/SPECS/xxx.spec

Где id - идентификатор секции в spec-файле:
%prep - p ( -bp )
%build - c ( -bc )
%install - i ( -bi )
%files - l ( -bl )

Полная сборка:

Выполняется после того, как последовательно прошлись по всем шагам:
    rpmbuild -ba --target $(uname -m) --clean ~/rpmbuild/SPECS/xxx.spec

Генерация gpg-ключа для подписывания пакетов:

gpg --gen-key

Добавление подписи к пакету: 

rpm --add-sign xxx.rpm

Автоматическое добавление подписи к пакету:

Сначала необходимо посмотреть список сгенерённых ключей:
$ gpg --fingerprint
/home/grin/.gnupg/pubring.gpg
-----------------------------
pub   2048R/8EF3B046 2015-01-26
      Key fingerprint = EBBC 7265 2A5E B117 E397  E63E FE30 9913 8EF3 B046
uid                  Rinat Gadelshin <rgadelsh@gmail.com>
sub   2048R/97A7AD93 2015-01-26

pub   2048R/52D7329A 2015-01-26
      Key fingerprint = 565C 5622 BD66 F17B DDB0  0378 CBF8 F0C1 52D7 329A
uid                  Rinat Gadelshin (grin) <rgadelsh@gmail.com>
sub   2048R/A394DD73 2015-01-26

Далее в файл ~/.rpmmacros необходимо добавить следующие строки:
%_signature gpg
%_gpg_name Rinat Gadelshin (grin) <rgadelsh@gmail.com>
 

По сути, мы прописываем строку uid, относящуюся к выбранному ключу (52D7329A из вывода команды gpg --fingerprint). Видно что для нашего ключа строка содержит комментарий (grin), а для другого ключа ( 8EF3B046 ) комментарий не содержится.


четверг, 10 ноября 2016 г.

Поиск библиотеки, содержащей определение функции

Переодически при компиляции сторонних продуктов возникает ошибка
 undefined reference to <function>
для какой либо функции. Обычно я гуглил имя функции и искал, что кто-нибудь скажет какую библиотеку надо прилинковать к проекту.
Вчера, в очередной раз столкнувшись с подобной проблемой написал, в терминале команду, которая ищет данную функцию.

function="dbus_watch_set_data"; \
for library in $(ls /usr/lib/*.so); do \
    res=$(readelf -s ${library} 2> /dev/null | grep ${function} | grep -v 00000000); \
    if [ ! -z "$res" ]; then \
        echo "${library}: $res"; \
        break; \
    fi; \
done; \
if [ -z "$res" ]; then \
    echo "function '${function}' not found"; \
fi

Соответственно вместо dbus_watch_set_data нужно подставлять имя искомой функции.
Также можно вместо /usr/lib/ вставлять другие директории, например /usr/local/lib.

Пример удачного поика:
[grin@grinvbox-ol65-x86 ~]$ function="dbus_watch_set_data"; for library in $(ls /usr/lib/*.so); do res=$(readelf -s ${library} 2> /dev/null | grep ${function} | grep -v 00000000); if [ ! -z "$res" ]; then echo "${library}: $res"; break; fi; done; if [ -z "$res" ]; then echo "function '${function}' not found"; fi
/usr/lib/libdbus-1.so:    473: 0002bdd0   111 FUNC    GLOBAL DEFAULT   12 dbus_watch_set_data@@LIBDBUS_1_3
  1410: 0002bdd0   111 FUNC    GLOBAL DEFAULT   12 dbus_watch_set_data

Функция dbus_watch_set_data найдена (2 раза) в библиотеке /usr/lib/libdbus-1.so


Пример неудачного поиска:
[grin@grinvbox-ol65-x86 ~]$ function="dbusx_watch_set_data"; for library in $(ls /usr/lib/*.so); do res=$(readelf -s ${library} 2> /dev/null | grep ${function} | grep -v 00000000); if [ ! -z "$res" ]; then echo "${library}: $res"; break; fi; done; if [ -z "$res" ]; then echo "function '${function}' not found"; fi
function 'dbusx_watch_set_data' not found

Функция dbusx_watch_set_data не найдена (нет такой функции).


P.S. для более детального понимания, рекомендую man readelf.

четверг, 29 января 2015 г.

Квота на размер папки в Linux

Предыстория
Для ftp сервера на Linux-е потребовалось установить ограничение на размер папки Upload.
В итоге был выбран следующий вариант ( оригинал был прочитан тут: forum.ubuntu.ru ).

Суть метода в следующем:
Создаём файл фиксированного размера (2 GiB - 512 блоков по 4 MiB).
dd if=/dev/zero of=/opt/ftp_upload_fs bs=4M count=512
Чем больше размер блока, тем быстрее будет создаваться, но блок полностью размещается в оперативной памяти, так что не задавайте размер блока в 1 GB, если в системе у вас всего 512 MB =)

Создаём внутри этого файла файловую систему.
mke2fs -F /opt/ftp_upload_fs

Создаём папку, куда будет примонтирован данный файл.
mkdir -p /srv/ftp/upload

Теперь можно вручную примонтировать файл к папке, и задать владельца для данной папки (т.к. после примонтирования владельцем папки станет root:root).
sudo mount -o loop /opt/ftp_upload_fs /srv/ftp/upload
sudo chown ftp:ftp /srv/ftp/upload

Что бы после перезагрузки файл автоматически монтировался к папке, пропишем в /etc/fstab соответствующую инструкцию.
sudo echo "/opt/ftp_upload_fs /srv/ftp/upload auto defaults 0 1" >> /etc/fstab

После перезагрузки файл будет подмонтирован в папку, но владельцем папки будет root. Сам файл монтируется как /dev/loop устройство, для которого не поддерживается опция uid. Поэтому в /etc/rc.local прописываем владельцем данной папки пользователя ftp.
echo "chown ftp:ftp /srv/ftp/upload" >> /etc/rc.local

пятница, 23 января 2015 г.

Упаковка своего ПО в rpm-пакет

Детально описание rpm-пакетов, и особенности их создания описаны тут (оригиналперевод).
В данной статье будет дана краткая справка для ленивых =).

среда, 21 января 2015 г.

Развёртывание своего YUM-репозитория

Мотивация

Для управления набором ПО в диспетчерском центре, который должен быть отключен от Internet, предлагается развернуть свой YUM-репозиторий. Программное обеспечение, необходимое для организации работы диспетчерского центра хранится в этом репозитории в виде rpm-пакетов.

Плюсы данного подхода видятся следующие:

  • легко отслеживать версию установленного ПО ( от разработчиков не требуется встраивать механизм поддержки версий в само ПО - версия в обязательном порядке указывается для RPM-пакета ).
  • легко обновлять ПО до новой версии ( делается одной командой с клиентской машины, на которую можно зайти удалённо по ssh ).
  • легко откатить ПО к старой версии, если с обновлённой версией заметны проблемы.
  • легко устанавливать ПО на ЗИП-машину, в соответствии с той ролью, для которой её настраивают.

пятница, 16 января 2015 г.

Тонкости создания rpm-пакетов

Внимательное отношение к эпохе пакета

При разрешении зависимостей, эпоха (Epoch) имеет более важное значение чем версия пакета.
Например если в пакете указать зависимость без эпохи

Requires: qt >= 4.7.4

А в системе установлена версия 4.6.3 первой эпохи

[grin@grinvb i686]$ yum info qt
Loaded plugins: refresh-packagekit, security
Installed Packages
Name        : qt
Arch        : i686
Epoch       : 1
Version     : 4.6.3
Release     : 1.el6
Size        : 35 M
Repo        : installed

То, при установки нашего пакета, rpm решит, что 4.6.3 более новая, чем требуемая 4.7.4, следовательно зависимость удовлетворена и можно ставить пакет, что является ошибкой.

среда, 19 ноября 2014 г.

Локальная загрузка в Linux без пароля ( single user mode )

Предыстория:
    Позвонил вечером коллега. Сказал, что не загружается компьютер на объекте. А утром 48-часовой тестовый прогон и всё должно обязательно работать. У него на объекте уже была ночь. С собой только ноут с виндой и загрузочной флешки с линуксом у него нет. В ходе обсуждения выяснилось, что на проблемном компьютере убился файл /lib/security/pam_unix.so - который отвечает за авторизацию. Задача была скопировать на данный комп файл со "здорового" компьютера. Но для этого нужен root-доступ.
Итак, нужно загрузиться локально ( имея физический доступ к компьютеру ), под пользователем root. Следовательно нужно загрузиться в Single User Mode.
В меню Grub данной опции на компьютере нет.

пятница, 29 ноября 2013 г.

Включение git-репозитория в svn-проект как svn:externals

Несмотря на то, что в своей работе я предпочитаю использовать распределённые системы контроля версий ( git / hg ), но переодически приходится работать в командах, использующих svn.

Итак, потребовалось, в svn-проекте использовать библиотеки, написанные другой ( дружественной командой ), но которые лежат в git репозитории.

После поиска в интернете решил сделать скриптового бота, для которого инициализирую git-svn репозиторий. Дальше робот будет опрашивать git - репозиторий, и при наличии изменений заливать их в svn - репозиторий.