LINUX.ORG.RU

Как еще обновить самого себя?

 ,


0

1

Приветствую.

Как я понимаю обычное решение это скопировать куда то новый бинарник, затем запустить его с какими то параметрами из своего процесса через exec* и уже в нем положить себя на свое старое место - неудобно в этом то, что нужно проверяться из какого места загружен и либо снова запускаться из старого места либо все время помнить что запущен из «клона», а нет ли более хитрого способа без внешнего кода на C/C++ подменить свой бинарник во время его исполнения???

может есть какие то штатные средства ОС?

★★★
Ответ на: комментарий от EXL

если не сложно киньте ссылку на этот пример?

по хрому помню только что он пишет что ему надо перезапуститься вручную

wolverin ★★★
() автор топика
Последнее исправление: wolverin (всего исправлений: 1)

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

alysnix ★★★
()
Ответ на: комментарий от wolverin

Автоматически делает только вирусня и софт, который ведет себя как вирусня.

Если на вашей важной машине не делается apt get update && apt get upgrade регулярно - то проблема начинается тут.

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

ну мое ПО как бэ не находится в репозитории и своего репозитория нет, но хочется чтобы бинарник мог сам себя обновить, когда узнает что версия свежая вышла

wolverin ★★★
() автор топика
Ответ на: комментарий от PPP328

Если на вашей важной машине не делается apt get update && apt get upgrade регулярно - то проблема начинается тут.

Где же тут проблема? В Ubuntu обновлялся раз в 4 года, когда выходил очередной LTS релиз. В Gentoo почаще обновляю, но честно говоря не слишком. Проблем не заметил.

unDEFER ★★★★★
()
Ответ на: комментарий от Radjah
	for (int i = 1; i < argc; ++i) {
		if (equal(argv[i], "-noupdate")) {
			needupdate = false;
		} else if (equal(argv[i], "-autostart")) {
			autostart = true;
		} else if (equal(argv[i], "-debug")) {
			debug = _debug = true;
                ... 13 проверок

Кто-нибудь, расскажите им про getopt. ну или хотя бы про массивы.

		} else if (equal(argv[i], "-key") && ++i < argc) {
			key = argv[i];
		} else if (equal(argv[i], "-workpath") && ++i < argc) {
			workDir = workdir = argv[i];

Я прям ощущаю четкий запах CVE

PPP328 ★★★★★
()
Последнее исправление: PPP328 (всего исправлений: 1)

Как я понимаю обычное решение это

… не заниматься фигней. Задачу обновления приложения решает менеджер пакетов - он сам подложит новый бинарник, так что все что надо - по сути сделать exec $@

Если же вы занимаетесь приседанием на лыжах в гамаке, то rename {current} {backup} ; mv {new} {current} ; rm {backup>} ; exec $@

no-dashi-v2 ★★★
()
Последнее исправление: no-dashi-v2 (всего исправлений: 1)

И да, расскажите, что вы будете делать, когда выпустите (а вы выпустите) битое обновление? Ваше ПО автоматически на него обновляется и вываливается в ошибку (или творит херню с системой пользователя (см. rm -rf /var от яндекса). Дальше что? Выпустить новую версию не поможет, потому что приложение падает. Откатиться не поможет - вы сразу обновитесь и сломаете. Вы предлагает каждому руками удалять ваше поделие и потом руками устанавливать версию+1? Отличный план.

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

PPP328 ★★★★★
()
Ответ на: комментарий от wolverin

Перезаписывать тот же самый файл (делать туда write) не стоит, а вот переименовать новый, чтобы он заменил старый - да.

Записи в каталоге ФС это по сути ссылки. Когда ты разлинковываешь старый файл, он исчезает из каталога, но ядро его «держит», пока на него есть открытые дескрипторы. И старый процесс работает из этого файла.

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

wandrien ★★
()
Ответ на: комментарий от wolverin

Хотел еще syncthing предложить посмотреть, но там golang и всё размазано по нескольким файлам.

По итогу там всё равно получается что-то типа «переименовать себя - записать новый файл - запустить новый - удалить старый» с промежуточными проверками целостности.

В винде такое тоже работает, но я не настоящий программист и не знаю все параметры блокировок файлов.

Для винды можно посмотреть исходники Miranda NG, там тоже похожим образом делается обновление.

Radjah ★★★★★
()

это скопировать куда то новый бинарник, затем запустить его с какими то параметрами из своего процесса через exec* и уже в нем положить себя на свое старое место

Зачем класть в другое место сначала? Не, для этого есть одна причина, но я уверен что ты о ней не подумал.

firkax ★★★★★
()

А что мешает переименовать текущий бинарик? Мы же не в винде!

Так делает install.

Так обновляется init в sysvinit без перезагрузки.

Но вот наличие свободного места нужно проверить.

vel ★★★★★
()
Последнее исправление: vel (всего исправлений: 1)
Ответ на: комментарий от wolverin

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

так же лоадер может проверять корректность системы и откатываться к дефолту или предыдущей рабочей конфигой

Morin ★★★★★
()
Последнее исправление: Morin (всего исправлений: 1)
Ответ на: комментарий от Morin

Как еще обновить самого себя?

репы никто не ломал

Причем тут репы? Сама исходная задача про обход реп и прочих внешних обновляторов.

Если нужны репы, то не было бы вопроса про обновление самого себя.

anonymous
()
Ответ на: комментарий от wolverin

три действия:

записать бинарик под новым именем и убедиться, что все хорошо.

переименовать из нового имени в текущее, старый при этом удалится.

перезапустить самого себя.

За что борьба? Обновить «непрерывно» работающий процесс?

vel ★★★★★
()
Последнее исправление: vel (всего исправлений: 1)
Ответ на: комментарий от PPP328

аше ПО автоматически на него обновляется и вываливается в ошибку (или творит херню с системой пользователя (см. rm -rf /var от яндекса)

Менеджер пакетов от этого не спасает.

her_s_gory
()

новый релиз кладётся в /opt/puper-soft-1.23.45, проводятся местные тесты, запускается..старая версия выключается перед запуском новой или уже после (если есть балансировщики и это возможно бесшовно).

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

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

MKuznetsov ★★★★★
()

Во время исполнения ? Ну вообще гипотетически можно например сделать mmap исполняемого кода нового бинарника и переключиться на него. Другой вопрос, что с танцами придётся и оригинальный бинарник загружать, по сути по принципу ВМ, когда ВМ компилирует пользовательский код и в исполняемой памяти запускает его, но это как по мне звучит странно, да и скорее всего помимо рисков написать ужасный код вместо простого, но рабочего вызывает вопросы мотивация. Хотя есть более простой вариант - буквально держать ВМ какого-нибудь языка сценариев, типо Lua и соответственно при обновлении обеспечить 1) хранение 2) процедуру восстановления состояния в новой версии по состоянию ВМ старой. В случае бинарника такое тоже возможно, но только если приложение разбить на плагины, обновлять только их, при условии, если можете обеспечить подгрузку символов с помощью libdl при условии низкосвязности среды, таким образом, чтобы выгрузка старого модуля не грохала приложение.

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 1)
Ответ на: комментарий от her_s_gory

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

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

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

Я помню в венде распространял обновления через бинарник в рабочей БД. Софтина смотрела что в БД повысилась версия, писала что надо обновиться, скачивала блоб из таблицы в БД и заменяла.

А иначе было никак, т.к. софтина была мордой к БД и несоответствие версии софтины с версией БД могло сломать всю консистентность данных. А пользаки иногда неделями софт не перезапускали.

ЗЫЖ Была ба софтина под линукс, это ничего бы не поменяло. Ну на край можно было закрывать соединение и писать чтобы обновлялись через ПМ и не пускать покуда не обновятся.

Loki13 ★★★★★
()
Ответ на: комментарий от Loki13

Ну на край можно было закрывать соединение и писать чтобы обновлялись через ПМ и не пускать покуда не обновятся.

Именно.

Вообще такие связки должны мета-пакетом ставиться.

PPP328 ★★★★★
()
Ответ на: комментарий от PPP328

Вообще такие связки должны мета-пакетом ставиться.

Каким метапакетом? БД с процедурами на сервере в серверной, а пользаки по четырем этажам офиса разбросаны, человек 100. Вот выкатили обнову на БД ночью, девочка с утра пришла и должна работать в свежей версии программы, которая соответствует версии БД. Я не про СУБД, а про БД в данном случае, а версия это просто версия данных, таблиц и процедур.

Да, наверное можно было бы чем-то вроде политик обновлять, но даже не уверен что это на линуксе сделать будет легко(уверен что очень сложно). На венде же вообще нереально почти.

Loki13 ★★★★★
()

Все делают так:

vitus@vitus-home:~/telegram$ ll
итого 179952
-rwxr-xr-x 1 vitus vitus 173649048 дек  4 22:35 Telegram
-rwxr-xr-x 1 vitus vitus  10615032 дек  4 22:35 Updater

Т.е. когда телеграмму надо обновиться, он запускает Updater, а сам закрывается, после обновления Updater, запускает Telegram, а сам закрывается.

Понятное дело, что Updater может быть не бинарником, а тупым скриптом.

vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 1)