Как утилизировать 4 сетевых порта 1000Mbps (+3 фото)
Эффективное использование нескольких сетевых портов для виртуальных машин, запущенных на сервере
( читать дальше... )
Эффективное использование нескольких сетевых портов для виртуальных машин, запущенных на сервере
( читать дальше... )
У нас в Красноярске в это время года пасмурно, погода портится, льют осенние дожди, серые тучи закрывают небо, отчего не хватает солнца, и вместе с ним нет и настроения. В Москве прохладно, но осенью, как у нас в Сибири, совсем не пахнет, а вместо этого светит солнце, днём даже пригревает. В общем, надо привыкать к новому климату.
Погода должна радовать, но старые привычки, что осенью всё серое и хочется чего-то светлого — не отпускают. Захотелось вернуться к светлым тонам в интерфейсе. На скриншоте закос под ACME (Plan9).
CRUX, FVWM с закосом под классику, — классику, по которой я уверен, уже тоскуют даже самые матёрые линуксоиды. URxvt, vim как IDE.
Для разнообразия были выбраны чуть разные оттенки жёлтого в urxvt и vim. И, как можно увидеть, к использованию предлагается как тёмный (dark), так и светлый (light) стиль оформления.
~/.Xresources
URxvt.cursorColor: #a6dcf8
URxvt.scrollBar: true
URxvt.scrollBar_right: true
URxvt.scrollstyle: plain
URxvt.scrollColor: #999957
!URxvt.background: #ffffec
!URxvt.foreground: #424242
URxvt.background: #1a1a1a
URxvt.foreground: #ffffec
URxvt.color0: #424242
URxvt.color1: #b8261e
URxvt.color2: #3e8630
URxvt.color3: #7f8f29
URxvt.color4: #2a8dc5
URxvt.color5: #8888c7
URxvt.color6: #6aa7a8
URxvt.color7: #999957
URxvt.color8: #eeeea7
URxvt.color9: #f2acaa
URxvt.color10: #98ce8f
URxvt.color11: #b6b79c
URxvt.color12: #a6dcf8
URxvt.color13: #d0d1f7
URxvt.color14: #b0eced
URxvt.color15: #ffffec
~/.vim/colors/acme.vim
highlight clear
highlight! Normal guibg=#ffffea guifg=#000000 ctermbg=230 ctermfg=232
highlight! NonText guibg=bg guifg=#ffffea ctermbg=bg ctermfg=230
highlight! StatusLine guibg=#aeeeee guifg=#000000 gui=NONE ctermbg=159 ctermfg=232 cterm=NONE
highlight! StatusLineNC guibg=#eaffff guifg=#000000 gui=NONE ctermbg=194 ctermfg=232 cterm=NONE
highlight! WildMenu guibg=#000000 guifg=#eaffff gui=NONE ctermbg=black ctermfg=159 cterm=NONE
highlight! VertSplit guibg=#ffffea guifg=#000000 gui=NONE ctermbg=159 ctermfg=232 cterm=NONE
highlight! Folded guibg=#cccc7c guifg=fg gui=italic ctermbg=187 ctermfg=fg cterm=italic
highlight! FoldColumn guibg=#fcfcce guifg=fg ctermbg=229 ctermfg=fg
highlight! Conceal guibg=bg guifg=fg gui=NONE ctermbg=bg ctermfg=fg cterm=NONE
highlight! LineNr guibg=bg guifg=#505050 gui=italic ctermbg=bg ctermfg=239 cterm=italic
highlight! Visual guibg=fg guifg=bg ctermbg=fg ctermfg=bg
highlight! CursorLine guibg=#ffffca guifg=fg ctermbg=230 ctermfg=fg
highlight! Pmenu guibg=bg guifg=fg ctermbg=bg ctermfg=fg
highlight! PmenuSel guibg=fg guifg=bg ctermbg=fg ctermfg=bg
highlight! Statement guibg=bg guifg=fg gui=italic ctermbg=bg ctermfg=fg cterm=italic
highlight! Identifier guibg=bg guifg=fg gui=bold ctermbg=bg ctermfg=fg cterm=bold
highlight! Type guibg=bg guifg=fg gui=bold ctermbg=bg ctermfg=fg cterm=bold
highlight! PreProc guibg=bg guifg=fg gui=bold ctermbg=bg ctermfg=fg cterm=bold
highlight! Constant guibg=bg guifg=#101010 gui=bold ctermbg=bg ctermfg=233 cterm=italic
highlight! Comment guibg=bg guifg=#303030 gui=italic ctermbg=bg ctermfg=236 cterm=italic
highlight! Special guibg=bg guifg=fg gui=bold ctermbg=bg ctermfg=fg cterm=bold
highlight! SpecialKey guibg=bg guifg=fg gui=bold ctermbg=bg ctermfg=fg cterm=bold
highlight! NonText guibg=bg guifg=fg gui=bold ctermbg=bg ctermfg=fg cterm=bold
highlight! Directory guibg=bg guifg=fg gui=bold ctermbg=bg ctermfg=fg cterm=bold
highlight! link Title Directory
highlight! link MoreMsg Comment
highlight! link Question Comment
hi link vimFunction Identifier
let g:colors_name = "acme"
~/.fvwm/config
DestroyModuleConfig FvwmIconMan:*
*FvwmIconMan: UseWinList true
*FvwmIconMan: Resolution global
*FvwmIconMan: Sort id
*FvwmIconMan: Shape true
*FvwmIconMan: Tips always
*FvwmIconMan: TipsDelays 0
*FvwmIconMan: TipsFont "xft:Sans:size=8"
*FvwmIconMan: TipsFormat "%t"
*FvwmIconMan: ManagerGeometry 1x1
*FvwmIconMan: ButtonGeometry 180x25
*FvwmIconMan: MaxButtonWidth 180
*FvwmIconMan: DrawIcons always
*FvwmIconMan: ReliefThickness 1
*FvwmIconMan: Format "%t"
*FvwmIconMan: Font "xft:Sans:size=10"
*FvwmIconMan: Action Mouse 0 A ret
*FvwmIconMan: Action Mouse 1 A sendcommand IconManClick
*FvwmIconMan: Action Mouse 3 A sendcommand "Menu MenuIconOps"
*FvwmIconMan: Title ""
DestroyModuleConfig TaskBar:*
*TaskBar: Geometry $[vp.width]x32+0-0
*TaskBar: Font "xft:Sans:size=10:antialias=True"
*TaskBar: (Container)
*TaskBar: (Container(Rows 1 Columns $[vp.width]), Padding 2 2, Frame 2)
PipeRead 'echo "*TaskBar: ($(($[vp.width] - 50))x1, Container, Frame 0)"'
*TaskBar: (Swallow FvwmIconMan 'Module FvwmIconMan', Frame 0)
*TaskBar: (End)
*TaskBar: (50x1, Container, Frame 0)
*TaskBar: (Container, Frame -1)
*TaskBar: (Swallow DateTime 'Module FvwmScript FvwmScript-DateTime', Frame 0)
*TaskBar: (End)
*TaskBar: (End)
*TaskBar: (End)
>>> Просмотр (3440x1440, 145 Kb)
хотелось бы реализовать автозапуск приложений а-ля rc.local, только получаемый из внешнего источника а-ля git.
ну казалось бы три строчки кода в тот-же rc.local добавить:
wait_inet_connection
git clone https://...
cd /project.git && ./autorun.inf
но думаю должно быть решение более изящное и интересное.
кто-нибудь сталкивался с такой задачей?
VDS с диском на 20гб, возможность загружать файлы размером пусть 100мб, возможность количества одновременных подключений 1000 клиентов.
А что если все они одновременно начнут загружать файл? Ну выполнять большой POST-запрос. nginx сохраняет его во временный файл, а дисковое пространство ограничено.
Пока POST-запрос не отправлен до конца, nginx не передаст его php-fpm, т.е. по сути мы имеем 1000 активных подключений, которые смеху ради поставились на паузу (ограничили скорость в 1кб) и потихоньку льют тебе файл на сервер.
И с точки зрения php ты ничего с этим сделать не сможешь, пока файл (POST) не придёт целиком, nginx не передаст его в работу на php-fpm, иначе было бы достаточно например сделать искусственное ограничение (на уровне приложения) в 10 пользователей, которые одновременно могут загружать файл.
Т.е. бэкед в этой ситуации вообще лох и ничего не может.
Поэтому такое ограничение необходимо установить на уровне nginx.
Как?
Смонтировать отдельную директорию, в виде отдельного файла (дискового образа) и когда там закончится место чтобы nginx выкидывал 50х ошибку клиенту? Чтобы место не закончилось на VDS, а в файле, клиенты всё равно будут страдать, а щито поделать...
Я всё могу понять, технология новая, требует обката, свежа, юна, под неё ещё ничего толком не написали, нету выбора WM на вкус и цвет, терминал какой дают, но в принципе, браузер запускается, а вся работа в терминале, в консольных приложениях, я готов пойти неудобства ради...
(chroot) /tmp/tmp.D80f2xWrcR: # prt-get depinst --test sway | grep -c xorg
28
мммм...
А зачем мне сырой Wayland с недоиксами в системе? Я уж тогда поставлю сотню пакетов xorg и не буду терпеть никаких неудобств.
Правильно понимаю, что на текущий момент невозможно иметь чистое Wayland окружение без иксовых зависимостей?
Изменится ли эта ситуация в будущем?
В тонкости-нюансы, что иксовые пакеты требует mesa, которую требует wayland, я не вдаюсь, я смотрю на итоговый результат, что Wayland это шляпа полностью зависимая от иксов.
Собственно, сабж.
Не могу осилить ничего сложнее bash и php, просто не понимаю ЗАЧЕМ!?
Создаю функцию, которая будет дёргать другие функции, дергаю динамические данные из массивов или базы данных, этого хватает для перекладывания файликов с места на место и создания образов и загрузки линуксов по сети, для записи и вывода статей на сайте, ну норм же.
Почитал новость о том, что в Linux приходит Rust, подумал, ну вот время для изучения C упущено, но сейчас начинается новая эпоха с Rust в ядре, чем чёрт не шутит, может стоит попробовать, авось, для ядра какие-нибудь приколюхи тоже смогу писать? НЕТ НЕ СМОГУ ПОТОМУ ЧТО Я ТУПОЙ(((((
https://doc.rust-lang.ru/book/ch03-01-variables-and-mutability.html#Затенение...
Затенение (переменных)
Я не понимаю что это и зачем это нужно.
fn main() {
let x = 5;
let x = x + 1;
{
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}
println!("The value of x is: {x}");
}
Почему нельзя из main вызвать функцию, которая сделает это самое x * 2 и напишет строчку, зачем было усложнять и придумывать какое-то { }.
fn main() {
let x = 5;
let x = x + 1;
x_multiple(x);
println!("The value of x is: {x}");
}
fn x_multiple(x: i32) {
let x = x * 2;
println!("The value of x in the inner scope is: {x}");
}
За достоверность синтаксиса не ручаюсь.
Я ещё могу как-то понять типы данных, ну там, один байтик 255 максимальное число, два байтика уже 255 * 255 = 65025 максимальное число, четыре байтика 255 * 255 * 255 * 255... Прикольно конечно, да, что 4 байтами можно кодировать большие числа, как это делают во всяких JPEG, PNG и т.д. бинарных форматах, что можно одним символом " " (пробел) описать число 32 т.к. это 32 символ в ASCII таблице.
Структуры в расте ещё какие-то, почему нельзя обойтись обычными массивами для хранения данных.
Классы в PHP не осилил, Rust похоже тоже не осилю.
Ну и что теперь, обратно в дворники идти?
Сервер HP DL380 Gen9, RAID-контроллер P440ar, 6 SAS HDD по 18TB в массиве RAID-0, файловая система ext4, картинка.
Просто «на холодную» смонтировал диск и просто вы только посмотрите:
# time find /mnt/disk2/
/mnt/disk2/
/mnt/disk2/lost+found
/mnt/disk2/vm
/mnt/disk2/vm/CRUX-WebServer-RootServer.img
/mnt/disk2/vm/CRUX-CorePorts.img
/mnt/disk2/vm/CRUX-DocumentsAndSettings.img
/mnt/disk2/vm/old
/mnt/disk2/vm/old/CRUX-WebServer-RootServer.img
/mnt/disk2/vm/old/CRUX-Worker2.img
/mnt/disk2/vm/old/CRUX-WebServer-RootServer-www_XXXXXXXX_ru.img
/mnt/disk2/vm/old/CRUX-Worker1.img
/mnt/disk2/vm/old/CRUX-WebServer-RootServer-www_XXXXXXXX_ru.img
/mnt/disk2/vm/old/CRUX-KVM-Host-XXXXXXXX_ru.img
/mnt/disk2/vm/old/CRUX-OneGigabyte.img
/mnt/disk2/vm/old/CRUX-KVM-Host-XXXXXXXX_ru.img
/mnt/disk2/vm/old/CRUX-WebServer-RootServer-www_XXXXXXXX_ru.img
real 0m8.957s
user 0m0.002s
sys 0m0.000s
Это оставило мне глубокую душевную рану, с такими результатами, я не ожидал.
С такими результатами этот сервер не то, что под торренты или условную файлопомойку, его под просмотр аниме через DLNA использовать сомнительно, его разве что для архивных бэкапов раз в год запускать... Чувствуется, что данные находились где-то на другом континенте.
С такими результатами, приходит понимание, что существует некий предел объёма данных в принципе, который допустимо использовать в рамках одной железки. Пусть это будет 10тб. Вместо одного LFF сервера взять несколько SFF, набить их дисками и распределять хранение данных между ними по сети, использовать какой-нибудь Ceph, да даже самописанный костыль, который будет проксировать файлики с разных серверов глядя на URL: /srv1/filename, /srv2/filename, /srv3/filename — будет быстрее и лучше.
Чем тупо взять много больших дисков и всё в RAID-0, и ожидать каких-то адекватных скоростей и отклика.
Какой самый большой объём данных вы щупали? Как считаете, не лучше ли такой объём данных распределить между несколькими железками, чем всё на одной хранить?
Приехала, значится, корзина, на 8 (восемь) 2.5" NVMe дисков. Вы не ослышались. NVMe диски в форм-факторе обычных 2.5" твердотельных накопителей. Ещё U.2 называется разъём.
https://www.netboot.ru/20220902_164630.jpg
https://www.netboot.ru/20220902_164639.jpg
https://www.netboot.ru/20220902_164650.jpg
Прикрутил корзину, а подключается она... Подключается она... Прямиком в рейзер! И разъём сильно отличается от обычного SAS-кабеля. И цвет кабелей, не сининький, а серенький. Такие дела.
https://www.netboot.ru/20220902_165313.jpg
https://www.netboot.ru/20220902_172005.jpg
https://www.netboot.ru/20220902_172016.jpg
Вместо обычных SATA/SAS-дисков у нас теперь подключаются NVMe-диски, и подключаются напрямую к линиям PCI, минуя какой-либо хардварный рейд-контроллер.
Получается что рейд-контроллеры — всё? В скором будущем их не станет, когда основная масса перейдёт с серверных SAS-дисков на NVMe U.2 диски?
А как же резервирование, зеркалирование дисков, вот это вот всё? Это получается же только софтварным путём только решается, т.е. будущее за mdadm?
Или NVMe диски будут существовать параллельно с SAS-дисками? И если кому-то надо аниме хранить, то тот будет использовать дисковые массивы с хардварными рейдами? А новые U.2 корзины для дисков они предназначены совсем для других задач?
Что вы думаете по этому поводу?
На чём лучше собирать CRUX?
Здравствуйте, кто пользуется тарифами операторов сотовой связи, на которых заявлен безлимит на мессенджеры, в частности интересует Telegram — он действительно безлимитный?
Есть идея поднять торрентокачалку на VDS, а затем скриптом отправлять самому себе файлы в Telegram, и получается на тарифе с безлимитными мессенджерами такие загрузки файлов не должны тарифицироваться.
Всё верно?
Для разбиения файлов по 2Гб есть split
.
Инструмент значения не имеет, proxmox, libvirt или что-то ещё.
Запущена виртуальная машина, нужно запустить её уже запущенную копию.
Никаких виртуальных дисков, файлов копировать не нужно т.к. ОС загружена в памяти.
Такое возможно?
УРА! УРА! УРА!
ДРУЗЬЯ! Новый релиз CRUX 3.7 вышел из стадии глубокого тестирования, пакетная база заморожена, а это значит... Это значит, что мы теперь можем более точно увидеть diff нового выпуска этого замурррчательного дистрибутива CRUX 3.7! УРА!
>>> CRUX 3.7 RC2 (1.1GB) — Скачать официальную сборку CRUX 3.7 RC2 с сайта автора.
Но у нас свой, особый путь, за что мы все так любим CRUX — за сорц-базед и красоту дистрибутива в своей простоте, в том числе за счёт элементарной пересборки пакетной базы. prt-get update -fr `prt-get listinst`
Поэтому... Поэтому прямо сейчас.
https://www.netboot.ru/Screenshot_2022-07-28_08-45-28.png — Прямо сейчас я с пылу-жару собираю новенькую пакетную базу на двух AMD EPYC 7742 [128 / 256] загрузившись в tmpfs!
>>> Скачать LIVE ISO (260MB) — Загрузочный ISO собранный при помощи моего booty, на последнем ядре Linux 5.18.14, который загрузит свеженький CRUX 3.7 прямо в tmpfs или overlayfs+squashfs на ваш выбор!
На секундочку, у меня есть последний CRUX 3.6 который мы хотим обновить до CRUX 3.7, какие различия версий пакетов?
# ports -d
Collection Name Port Installed
core bash 5.1.16-2 5.1.16-1
core binutils 2.38-1 2.35.2-1
core dhcpcd 9.4.1-2 9.4.1-1
core exim 4.96-1 4.95-1
core filesystem 3.7-2 3.6-2
core gcc 12.1.0-1 10.4.0-1
core glibc 2.35-2 2.32-7
core glibc-32 2.35-1 2.32-7
core less 608-1 590-1
core libffi 3.4.2-1 3.3-1
core libnsl 2.0.0-1 1.3.0-1
core libtirpc 1.3.2-2 1.3.2-1
core mlocate 0.26-3 0.26-2
core openssl 3.0.5-1 1.1.1q-1
core perl 5.36.0-1 5.32.1-1
core pkgutils 5.40.9-1 5.40.7-1
core ports 1.6-3 1.6-2
core procps 4.0.0-1 3.3.17-1
core prt-get 5.19.6-1 5.19.5-2
core python3 3.10.5-1 3.9.13-1
core python3-setuptools 63.1.0-1 63.2.0-1
core rc 2.32-2 2.31-3
core rdate 0.10-1 0.9-1
core signify 0.10-1 20200707-1
opt wget 1.21.2-1 1.21.3-1
Более детально посмотрим различия CRUX 3.6 и грядущего CRUX 3.7!
# ls /tmp/tmp.O3X39q7qQf/usr/ports/core/ > /tmp/3.7
# ls ports-3.6.1/core/ > /tmp/3.6
# diff /tmp/3.6 /tmp/3.7
12a13
> cmake
20a22
> dumb_runtime_dir
46a49,50
> jansson
> jsoncpp
52a57
> libedit
54a60
> libmnl
56a63,64
> libnftnl
> libnghttp2
58a67
> libpcre2
62a72
> libuv
63a74
> lzlib
68a80
> meson
72a85,86
> nftables
> ninja
78c92
< pkg-config
---
> pkgconf
84a99
> python3-setuptools
87a103
> rhash
Добавлено в core:
Удалено из core:
Насколько же новый CRUX 3.7 стал жирнее в сравнении с предыдущим CRUX 3.6?
Установим оба!
Правила следующие: установки одного core недостаточно для работы CRUX, если речь не идёт об chroot, мы же хотим загружаться в установленную систему? Поэтому ставить мы будем не только core, а дополнительно возьмём загрузчик grub2 в качестве обязательного к установке пакета.
CRUX 3.6
# mkdir /tmp/crux36 ; mount -t tmpfs tmpfs /tmp/crux36 ; mkdir -p /tmp/crux36/var/lib/pkg ; touch /tmp/crux36/var/lib/pkg/db ; for pkg in ports-3.6.1/*/*/*.pkg.tar.xz ; do echo Install $pkg ... ; pkgadd --root /tmp/crux36 $pkg ; done
Install ports-3.6.1/core/acl/acl#2.3.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/attr/attr#2.5.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/autoconf/autoconf#2.71-1.pkg.tar.xz ...
Install ports-3.6.1/core/automake/automake#1.16.5-1.pkg.tar.xz ...
Install ports-3.6.1/core/bash/bash#5.1.16-1.pkg.tar.xz ...
Install ports-3.6.1/core/bc/bc#1.07.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/binutils/binutils#2.35.2-1.pkg.tar.xz ...
Install ports-3.6.1/core/bison/bison#3.8.2-1.pkg.tar.xz ...
Install ports-3.6.1/core/bzip2/bzip2#1.0.8-3.pkg.tar.xz ...
Install ports-3.6.1/core/ca-certificates/ca-certificates#20220719-1.pkg.tar.xz ...
Install ports-3.6.1/core/coreutils/coreutils#9.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/cpio/cpio#2.13-2.pkg.tar.xz ...
Install ports-3.6.1/core/curl/curl#7.84.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/dash/dash#0.5.11.5-1.pkg.tar.xz ...
Install ports-3.6.1/core/db/db#5.3.28-2.pkg.tar.xz ...
Install ports-3.6.1/core/dcron/dcron#4.5-3.pkg.tar.xz ...
Install ports-3.6.1/core/dhcpcd/dhcpcd#9.4.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/diffutils/diffutils#3.8-1.pkg.tar.xz ...
Install ports-3.6.1/core/e2fsprogs/e2fsprogs#1.46.5-1.pkg.tar.xz ...
Install ports-3.6.1/core/ed/ed#1.18-1.pkg.tar.xz ...
Install ports-3.6.1/core/elfutils/elfutils#0.187-1.pkg.tar.xz ...
Install ports-3.6.1/core/eudev/eudev#3.2.11-1.pkg.tar.xz ...
Install ports-3.6.1/core/exim/exim#4.95-1.pkg.tar.xz ...
Install ports-3.6.1/core/expat/expat#2.4.8-1.pkg.tar.xz ...
Install ports-3.6.1/core/file/file#5.42-1.pkg.tar.xz ...
Install ports-3.6.1/core/filesystem/filesystem#3.6-2.pkg.tar.xz ...
Install ports-3.6.1/core/findutils/findutils#4.9.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/flex/flex#2.6.4-2.pkg.tar.xz ...
Install ports-3.6.1/core/gawk/gawk#5.1.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/gcc/gcc#10.4.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/gdbm/gdbm#1.23-1.pkg.tar.xz ...
Install ports-3.6.1/core/gettext/gettext#0.21-1.pkg.tar.xz ...
Install ports-3.6.1/core/glibc-32/glibc-32#2.32-7.pkg.tar.xz ...
Install ports-3.6.1/core/glibc/glibc#2.32-7.pkg.tar.xz ...
Install ports-3.6.1/core/gperf/gperf#3.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/grep/grep#3.7-1.pkg.tar.xz ...
Install ports-3.6.1/core/groff/groff#1.22.4-1.pkg.tar.xz ...
Install ports-3.6.1/core/gzip/gzip#1.12-1.pkg.tar.xz ...
Install ports-3.6.1/core/hdparm/hdparm#9.64-1.pkg.tar.xz ...
Install ports-3.6.1/core/httpup/httpup#0.5.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/iana-etc/iana-etc#20220719-1.pkg.tar.xz ...
Install ports-3.6.1/core/inetutils/inetutils#2.3-1.pkg.tar.xz ...
Install ports-3.6.1/core/iproute2/iproute2#5.18.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/iptables/iptables#1.8.8-1.pkg.tar.xz ...
Install ports-3.6.1/core/kbd/kbd#2.5.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/kmod/kmod#30-1.pkg.tar.xz ...
Install ports-3.6.1/core/less/less#590-1.pkg.tar.xz ...
Install ports-3.6.1/core/libarchive/libarchive#3.6.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/libcap/libcap#2.65-1.pkg.tar.xz ...
Install ports-3.6.1/core/libdevmapper/libdevmapper#1.02.185-1.pkg.tar.xz ...
Install ports-3.6.1/core/libffi/libffi#3.3-1.pkg.tar.xz ...
Install ports-3.6.1/core/libgmp/libgmp#6.2.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/libmpc/libmpc#1.2.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/libmpfr/libmpfr#4.1.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/libnsl/libnsl#1.3.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/libpcre/libpcre#8.45-1.pkg.tar.xz ...
Install ports-3.6.1/core/libpipeline/libpipeline#1.5.6-1.pkg.tar.xz ...
Install ports-3.6.1/core/libtirpc/libtirpc#1.3.2-1.pkg.tar.xz ...
Install ports-3.6.1/core/libtool/libtool#2.4.7-1.pkg.tar.xz ...
Install ports-3.6.1/core/libusb/libusb#1.0.26-1.pkg.tar.xz ...
Install ports-3.6.1/core/linux-pam/linux-pam#1.5.2-3.pkg.tar.xz ...
Install ports-3.6.1/core/lzo/lzo#2.10-1.pkg.tar.xz ...
Install ports-3.6.1/core/m4/m4#1.4.19-1.pkg.tar.xz ...
Install ports-3.6.1/core/make/make#4.3-1.pkg.tar.xz ...
Install ports-3.6.1/core/man-db/man-db#2.10.2-1.pkg.tar.xz ...
Install ports-3.6.1/core/man-pages/man-pages#5.13-1.pkg.tar.xz ...
Install ports-3.6.1/core/mlocate/mlocate#0.26-2.pkg.tar.xz ...
Install ports-3.6.1/core/mpdecimal/mpdecimal#2.5.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/nasm/nasm#2.15.05-1.pkg.tar.xz ...
Install ports-3.6.1/core/ncurses/ncurses#6.3-1.pkg.tar.xz ...
Install ports-3.6.1/core/openssh/openssh#9.0p1-1.pkg.tar.xz ...
Install ports-3.6.1/core/openssl/openssl#1.1.1q-1.pkg.tar.xz ...
Install ports-3.6.1/core/patch/patch#2.7.6.17-9c98-1.pkg.tar.xz ...
Install ports-3.6.1/core/pciutils/pciutils#3.8.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/perl/perl#5.32.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/pkg-config/pkg-config#0.29.2-1.pkg.tar.xz ...
Install ports-3.6.1/core/pkgutils/pkgutils#5.40.7-1.pkg.tar.xz ...
Install ports-3.6.1/core/ports/ports#1.6-2.pkg.tar.xz ...
Install ports-3.6.1/core/procps/procps#3.3.17-1.pkg.tar.xz ...
Install ports-3.6.1/core/prt-get/prt-get#5.19.5-2.pkg.tar.xz ...
Install ports-3.6.1/core/psmisc/psmisc#23.5-1.pkg.tar.xz ...
Install ports-3.6.1/core/python3/python3#3.9.13-1.pkg.tar.xz ...
Install ports-3.6.1/core/rc/rc#2.31-3.pkg.tar.xz ...
Install ports-3.6.1/core/rdate/rdate#0.9-1.pkg.tar.xz ...
Install ports-3.6.1/core/readline/readline#8.1.2-1.pkg.tar.xz ...
Install ports-3.6.1/core/rsync/rsync#3.2.4-1.pkg.tar.xz ...
Install ports-3.6.1/core/sed/sed#4.8-1.pkg.tar.xz ...
Install ports-3.6.1/core/shadow/shadow#4.11.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/signify/signify#20200707-1.pkg.tar.xz ...
Install ports-3.6.1/core/sqlite3/sqlite3#3.39.2-1.pkg.tar.xz ...
Install ports-3.6.1/core/start-stop-daemon/start-stop-daemon#20210417-1.pkg.tar.xz ...
Install ports-3.6.1/core/sudo/sudo#1.9.11p3-1.pkg.tar.xz ...
Install ports-3.6.1/core/sysfsutils/sysfsutils#2.1.1-1.pkg.tar.xz ...
Install ports-3.6.1/core/sysklogd/sysklogd#2.4.0-1.pkg.tar.xz ...
Install ports-3.6.1/core/sysvinit/sysvinit#3.04-1.pkg.tar.xz ...
Install ports-3.6.1/core/tar/tar#1.34-1.pkg.tar.xz ...
Install ports-3.6.1/core/time/time#1.9-1.pkg.tar.xz ...
Install ports-3.6.1/core/tzdata/tzdata#2022a-1.pkg.tar.xz ...
Install ports-3.6.1/core/usbutils/usbutils#014-1.pkg.tar.xz ...
Install ports-3.6.1/core/util-linux/util-linux#2.38-1.pkg.tar.xz ...
Install ports-3.6.1/core/vim/vim#9.0.0054-1.pkg.tar.xz ...
Install ports-3.6.1/core/wget/wget#1.21.3-1.pkg.tar.xz ...
Install ports-3.6.1/core/which/which#2.21-2.pkg.tar.xz ...
Install ports-3.6.1/core/xz/xz#5.2.5-1.pkg.tar.xz ...
Install ports-3.6.1/core/zlib/zlib#1.2.12-1.pkg.tar.xz ...
Install ports-3.6.1/core/zstd/zstd#1.5.2-1.pkg.tar.xz ...
Install ports-3.6.1/opt/fakeroot/fakeroot#1.29-1.pkg.tar.xz ...
Install ports-3.6.1/opt/freetype/freetype#2.12.1-1.pkg.tar.xz ...
Install ports-3.6.1/opt/grub2-efi/grub2-efi#2.06-1.pkg.tar.xz ...
Install ports-3.6.1/opt/grub2/grub2#2.06-2.pkg.tar.xz ...
Install ports-3.6.1/opt/iputils/iputils#20211215-1.pkg.tar.xz ...
Install ports-3.6.1/opt/libpng/libpng#1.6.37-1.pkg.tar.xz ...
Install ports-3.6.1/opt/meson/meson#0.63.0-1.pkg.tar.xz ...
Install ports-3.6.1/opt/ninja/ninja#1.11.0-1.pkg.tar.xz ...
Install ports-3.6.1/opt/python3-setuptools/python3-setuptools#63.2.0-1.pkg.tar.xz ...
# df -h /tmp/crux36
Filesystem Size Used Avail Use% Mounted on
tmpfs 40G 761M 39G 2% /tmp/crux36
761МБ занимает обновлённый CRUX 3.6 в установленном виде!
CRUX 3.7
# mkdir /tmp/crux37 ; mount -t tmpfs tmpfs /tmp/crux37 ; mkdir -p /tmp/crux37/var/lib/pkg ; touch /tmp/crux37/var/lib/pkg/db ; for pkg in ports-3.7/*/*/*.pkg.tar.xz ; do echo Install $pkg ... ; pkgadd --root /tmp/crux37 $pkg ; done
Install ports-3.7/core/acl/acl#2.3.1-1.pkg.tar.xz ...
Install ports-3.7/core/attr/attr#2.5.1-1.pkg.tar.xz ...
Install ports-3.7/core/autoconf/autoconf#2.71-1.pkg.tar.xz ...
Install ports-3.7/core/automake/automake#1.16.5-1.pkg.tar.xz ...
Install ports-3.7/core/bash/bash#5.1.16-2.pkg.tar.xz ...
Install ports-3.7/core/bc/bc#1.07.1-1.pkg.tar.xz ...
Install ports-3.7/core/binutils/binutils#2.38-1.pkg.tar.xz ...
Install ports-3.7/core/bison/bison#3.8.2-1.pkg.tar.xz ...
Install ports-3.7/core/bzip2/bzip2#1.0.8-3.pkg.tar.xz ...
Install ports-3.7/core/ca-certificates/ca-certificates#20220719-1.pkg.tar.xz ...
Install ports-3.7/core/cmake/cmake#3.23.2-1.pkg.tar.xz ...
Install ports-3.7/core/coreutils/coreutils#9.1-1.pkg.tar.xz ...
Install ports-3.7/core/cpio/cpio#2.13-2.pkg.tar.xz ...
Install ports-3.7/core/curl/curl#7.84.0-1.pkg.tar.xz ...
Install ports-3.7/core/dash/dash#0.5.11.5-1.pkg.tar.xz ...
Install ports-3.7/core/db/db#5.3.28-2.pkg.tar.xz ...
Install ports-3.7/core/dcron/dcron#4.5-3.pkg.tar.xz ...
Install ports-3.7/core/dhcpcd/dhcpcd#9.4.1-2.pkg.tar.xz ...
Install ports-3.7/core/diffutils/diffutils#3.8-1.pkg.tar.xz ...
Install ports-3.7/core/dumb_runtime_dir/dumb_runtime_dir#1.0.4-1.pkg.tar.xz ...
Install ports-3.7/core/e2fsprogs/e2fsprogs#1.46.5-1.pkg.tar.xz ...
Install ports-3.7/core/ed/ed#1.18-1.pkg.tar.xz ...
Install ports-3.7/core/elfutils/elfutils#0.187-1.pkg.tar.xz ...
Install ports-3.7/core/eudev/eudev#3.2.11-1.pkg.tar.xz ...
Install ports-3.7/core/exim/exim#4.96-1.pkg.tar.xz ...
Install ports-3.7/core/expat/expat#2.4.8-1.pkg.tar.xz ...
Install ports-3.7/core/file/file#5.42-1.pkg.tar.xz ...
Install ports-3.7/core/filesystem/filesystem#3.7-2.pkg.tar.xz ...
Install ports-3.7/core/findutils/findutils#4.9.0-1.pkg.tar.xz ...
Install ports-3.7/core/flex/flex#2.6.4-2.pkg.tar.xz ...
Install ports-3.7/core/gawk/gawk#5.1.1-1.pkg.tar.xz ...
Install ports-3.7/core/gcc/gcc#12.1.0-1.pkg.tar.xz ...
Install ports-3.7/core/gdbm/gdbm#1.23-1.pkg.tar.xz ...
Install ports-3.7/core/gettext/gettext#0.21-1.pkg.tar.xz ...
Install ports-3.7/core/glibc-32/glibc-32#2.35-1.pkg.tar.xz ...
Install ports-3.7/core/glibc/glibc#2.35-2.pkg.tar.xz ...
Install ports-3.7/core/gperf/gperf#3.1-1.pkg.tar.xz ...
Install ports-3.7/core/grep/grep#3.7-1.pkg.tar.xz ...
Install ports-3.7/core/groff/groff#1.22.4-1.pkg.tar.xz ...
Install ports-3.7/core/gzip/gzip#1.12-1.pkg.tar.xz ...
Install ports-3.7/core/hdparm/hdparm#9.64-1.pkg.tar.xz ...
Install ports-3.7/core/httpup/httpup#0.5.0-1.pkg.tar.xz ...
Install ports-3.7/core/iana-etc/iana-etc#20220719-1.pkg.tar.xz ...
Install ports-3.7/core/inetutils/inetutils#2.3-1.pkg.tar.xz ...
Install ports-3.7/core/iproute2/iproute2#5.18.0-1.pkg.tar.xz ...
Install ports-3.7/core/iptables/iptables#1.8.8-1.pkg.tar.xz ...
Install ports-3.7/core/jansson/jansson#2.14-1.pkg.tar.xz ...
Install ports-3.7/core/jsoncpp/jsoncpp#1.9.5-1.pkg.tar.xz ...
Install ports-3.7/core/kbd/kbd#2.5.1-1.pkg.tar.xz ...
Install ports-3.7/core/kmod/kmod#30-1.pkg.tar.xz ...
Install ports-3.7/core/less/less#608-1.pkg.tar.xz ...
Install ports-3.7/core/libarchive/libarchive#3.6.1-1.pkg.tar.xz ...
Install ports-3.7/core/libcap/libcap#2.65-1.pkg.tar.xz ...
Install ports-3.7/core/libdevmapper/libdevmapper#1.02.185-1.pkg.tar.xz ...
Install ports-3.7/core/libedit/libedit#20210910_3.1-1.pkg.tar.xz ...
Install ports-3.7/core/libffi/libffi#3.4.2-1.pkg.tar.xz ...
Install ports-3.7/core/libgmp/libgmp#6.2.1-1.pkg.tar.xz ...
Install ports-3.7/core/libmnl/libmnl#1.0.5-1.pkg.tar.xz ...
Install ports-3.7/core/libmpc/libmpc#1.2.1-1.pkg.tar.xz ...
Install ports-3.7/core/libmpfr/libmpfr#4.1.0-1.pkg.tar.xz ...
Install ports-3.7/core/libnftnl/libnftnl#1.2.2-1.pkg.tar.xz ...
Install ports-3.7/core/libnghttp2/libnghttp2#1.48.0-1.pkg.tar.xz ...
Install ports-3.7/core/libnsl/libnsl#2.0.0-1.pkg.tar.xz ...
Install ports-3.7/core/libpcre/libpcre#8.45-1.pkg.tar.xz ...
Install ports-3.7/core/libpcre2/libpcre2#10.40-1.pkg.tar.xz ...
Install ports-3.7/core/libpipeline/libpipeline#1.5.6-1.pkg.tar.xz ...
Install ports-3.7/core/libtirpc/libtirpc#1.3.2-2.pkg.tar.xz ...
Install ports-3.7/core/libtool/libtool#2.4.7-1.pkg.tar.xz ...
Install ports-3.7/core/libusb/libusb#1.0.26-1.pkg.tar.xz ...
Install ports-3.7/core/libuv/libuv#1.44.1-1.pkg.tar.xz ...
Install ports-3.7/core/linux-pam/linux-pam#1.5.2-3.pkg.tar.xz ...
Install ports-3.7/core/lzlib/lzlib#1.12-1.pkg.tar.xz ...
Install ports-3.7/core/lzo/lzo#2.10-1.pkg.tar.xz ...
Install ports-3.7/core/m4/m4#1.4.19-1.pkg.tar.xz ...
Install ports-3.7/core/make/make#4.3-1.pkg.tar.xz ...
Install ports-3.7/core/man-db/man-db#2.10.2-1.pkg.tar.xz ...
Install ports-3.7/core/man-pages/man-pages#5.13-1.pkg.tar.xz ...
Install ports-3.7/core/meson/meson#0.63.0-1.pkg.tar.xz ...
Install ports-3.7/core/mlocate/mlocate#0.26-3.pkg.tar.xz ...
Install ports-3.7/core/mpdecimal/mpdecimal#2.5.1-1.pkg.tar.xz ...
Install ports-3.7/core/nasm/nasm#2.15.05-1.pkg.tar.xz ...
Install ports-3.7/core/ncurses/ncurses#6.3-1.pkg.tar.xz ...
Install ports-3.7/core/nftables/nftables#1.0.4-1.pkg.tar.xz ...
Install ports-3.7/core/ninja/ninja#1.11.0-1.pkg.tar.xz ...
Install ports-3.7/core/openssh/openssh#9.0p1-1.pkg.tar.xz ...
Install ports-3.7/core/openssl/openssl#3.0.5-1.pkg.tar.xz ...
Install ports-3.7/core/patch/patch#2.7.6.17-9c98-1.pkg.tar.xz ...
Install ports-3.7/core/pciutils/pciutils#3.8.0-1.pkg.tar.xz ...
Install ports-3.7/core/perl/perl#5.36.0-1.pkg.tar.xz ...
Install ports-3.7/core/pkgconf/pkgconf#1.8.0-1.pkg.tar.xz ...
Install ports-3.7/core/pkgutils/pkgutils#5.40.9-1.pkg.tar.xz ...
Install ports-3.7/core/ports/ports#1.6-3.pkg.tar.xz ...
Install ports-3.7/core/procps/procps#4.0.0-1.pkg.tar.xz ...
Install ports-3.7/core/prt-get/prt-get#5.19.6-1.pkg.tar.xz ...
Install ports-3.7/core/psmisc/psmisc#23.5-1.pkg.tar.xz ...
Install ports-3.7/core/python3-setuptools/python3-setuptools#63.1.0-1.pkg.tar.xz ...
Install ports-3.7/core/python3/python3#3.10.5-1.pkg.tar.xz ...
Install ports-3.7/core/rc/rc#2.32-2.pkg.tar.xz ...
Install ports-3.7/core/rdate/rdate#0.10-1.pkg.tar.xz ...
Install ports-3.7/core/readline/readline#8.1.2-1.pkg.tar.xz ...
Install ports-3.7/core/rhash/rhash#1.4.3-1.pkg.tar.xz ...
Install ports-3.7/core/rsync/rsync#3.2.4-1.pkg.tar.xz ...
Install ports-3.7/core/sed/sed#4.8-1.pkg.tar.xz ...
Install ports-3.7/core/shadow/shadow#4.11.1-1.pkg.tar.xz ...
Install ports-3.7/core/signify/signify#0.10-1.pkg.tar.xz ...
Install ports-3.7/core/sqlite3/sqlite3#3.39.2-1.pkg.tar.xz ...
Install ports-3.7/core/start-stop-daemon/start-stop-daemon#20210417-1.pkg.tar.xz ...
Install ports-3.7/core/sudo/sudo#1.9.11p3-1.pkg.tar.xz ...
Install ports-3.7/core/sysfsutils/sysfsutils#2.1.1-1.pkg.tar.xz ...
Install ports-3.7/core/sysklogd/sysklogd#2.4.0-1.pkg.tar.xz ...
Install ports-3.7/core/sysvinit/sysvinit#3.04-1.pkg.tar.xz ...
Install ports-3.7/core/tar/tar#1.34-1.pkg.tar.xz ...
Install ports-3.7/core/time/time#1.9-1.pkg.tar.xz ...
Install ports-3.7/core/tzdata/tzdata#2022a-1.pkg.tar.xz ...
Install ports-3.7/core/usbutils/usbutils#014-1.pkg.tar.xz ...
Install ports-3.7/core/util-linux/util-linux#2.38-1.pkg.tar.xz ...
Install ports-3.7/core/vim/vim#9.0.0054-1.pkg.tar.xz ...
Install ports-3.7/core/which/which#2.21-2.pkg.tar.xz ...
Install ports-3.7/core/xz/xz#5.2.5-1.pkg.tar.xz ...
Install ports-3.7/core/zlib/zlib#1.2.12-1.pkg.tar.xz ...
Install ports-3.7/core/zstd/zstd#1.5.2-1.pkg.tar.xz ...
Install ports-3.7/opt/fakeroot/fakeroot#1.29-1.pkg.tar.xz ...
Install ports-3.7/opt/freetype/freetype#2.12.1-1.pkg.tar.xz ...
Install ports-3.7/opt/grub2-efi/grub2-efi#2.06-1.pkg.tar.xz ...
Install ports-3.7/opt/grub2/grub2#2.06-2.pkg.tar.xz ...
Install ports-3.7/opt/libpng/libpng#1.6.37-1.pkg.tar.xz ...
# df -h /tmp/crux37
Filesystem Size Used Avail Use% Mounted on
tmpfs 40G 833M 39G 3% /tmp/crux37
833M занимает последний CRUX 3.7 в установленном виде!
Даже не смотря на то, что часть ключевых пакетов из opt была перемещена в core, форы новому CRUX 3.7 это не дало.
Факт! CRUX 3.7 стал жирнее на 72 мегабайта!
Но это ещё не всё, давайте проведём другой более интересный эксперимент, всё таки нам нужно установить CRUX как операционную систему.
Для этого мы создадим образ виртуальной машины размером ровно 1,000,000,000 Байт == 1 ГБайт! Поместится ли наш жирненький пингвин в ней?
Почему выбран именно такой размер файла образа? Да всё просто. Для установки системы на VDS намного проще сперва развернуть систему локально в виртуальной машине, настроить её, а затем этот образ с системой целиком залить по сети на диск VDS, используя команду wget -qO - site/raw_image | dd of=/dev/vda status=progress
, поэтому в наших интересах получить оптимальный размер для такого образа диска.
Почему жирненький пингвин может не поместиться? Потому что 1 Гбайт будет занимать не столько сам пингвин, сколько мета-информация о разделах диска, файловая система и тому подобное. Может и не влезть. Да.
И так, погнали!
# qemu-img create -f raw vm/CRUX-3-6.img 1000000000
Formatting 'vm/CRUX-3-6.img', fmt=raw size=1000000000
# qemu-img create -f raw vm/CRUX-3-7.img 1000000000
Formatting 'vm/CRUX-3-7.img', fmt=raw size=1000000000
# ls -la vm/
total 81261288
drwxr-xr-x 3 root root 4096 Jul 28 06:40 .
drwxr-x--- 9 root root 4096 Jul 27 13:24 ..
-rw-r--r-- 1 root root 1000000000 Jul 28 06:41 CRUX-3-6.img
-rw-r--r-- 1 root root 1000000000 Jul 28 06:41 CRUX-3-7.img
-rw-r--r-- 1 root root 30000000000 Jul 28 06:41 CRUX-CorePorts.img
-rw-r--r-- 1 root root 50000000000 Jul 28 06:35 CRUX-DocumentsAndSettings.img
-rw-r--r-- 1 root root 10000000000 Jul 19 08:37 CRUX-WebServer-RootServer.img
drwxr-xr-x 2 root root 4096 Jul 18 14:37 old
Абсолютно все те же самые пакеты будут установлены в виртуальных машинах.
Произведём установку CRUX 3.6 и CRUX 3.7 на образы виртуалок как в chroot, а затем установим загрузчик grub2 и подготовим образы дисков к загрузке внутри уже собственных виртуальных машин!
# qemu-system-x86_64 \
-enable-kvm \
-smp $(nproc) \
-m 12G \
-nic tap,ifname=tap1,mac=52:54:00:00:00:01 \
-daemonize \
-vnc :0,to=99,id=default \
-drive file=vm/CRUX-CorePorts.img,format=raw \
-drive file=vm/CRUX-3-6.img,format=raw \
-drive file=vm/CRUX-3-7.img,format=raw
VNC server running on 0.0.0.0:5900
Для этого я запускаю свою основную виртуалку с CRUX, куда подключаю диски, на которые будут установлены другие системы.
Зайдём на виртуалку, разметим диски, создадим один корневой раздел под ext4.
# fdisk -l /dev/sdb /dev/sdc
Disk /dev/sdb: 953.67 MiB, 1000000000 bytes, 1953125 sectors
Device Boot Start End Sectors Size Id Type
/dev/sdb1 * 2048 1953124 1951077 952.7M 83 Linux
Disk /dev/sdc: 953.67 MiB, 1000000000 bytes, 1953125 sectors
Device Boot Start End Sectors Size Id Type
/dev/sdc1 * 2048 1953124 1951077 952.7M 83 Linux
Обратите внимание! В реальности 952M нам доступно, а мы ещё даже не создали файловую систему.
# mke2fs -t ext4 /dev/sdb1
# mount /dev/sdb1 /mnt
# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 920M 24K 856M 1% /mnt
Уже 856M нам осталось доступно!
# mkdir -p /mnt/var/lib/pkg ; touch /mnt/var/lib/pkg/db ; for pkg in ports-3.6.1/*/*/*.pkg.tar.xz ; do pkgadd -r /mnt $pkg ; done
# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 920M 766M 91M 90% /mnt
Вот и приехали!
CRUX 3.6, из одного гигабайта (1,000,000,000 байт) образа диска у нас осталось 91 мегабайт свободного пространства, это пока ещё без ядра.
Проделаем тоже самое с CRUX 3.7.
# mke2fs -t ext4 /dev/sdc1
# mount /dev/sdc1 /mnt
# mkdir -p /mnt/var/lib/pkg ; touch /mnt/var/lib/pkg/db ; for pkg in ports-3.7/*/*/*.pkg.tar.xz ; do pkgadd -r /mnt $pkg ; done
# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
/dev/sdc1 920M 838M 18M 98% /mnt
Установленный CRUX 3.7 на диск размером 1,000,000,000 байт оставил нам всего 18 мегабайт свободного пространства!
Для обеих систем соберём последнее ванильное ядро Linux 5.18.14
# wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.18.14.tar.xz
# tar xf linux-5.18.14.tar.xz
# cd linux-5.18.14
# make mrproper
# make defconfig
# make kvm_guest.config
# scripts/config -e CONFIG_CRYPTO_ECDSA
# scripts/config -e CONFIG_WIREGUARD
# make olddefconfig
kvm_guest.config
включает все необходимые драйверы для системы, которая будет работать в виртуальной машине. Для себя включил Wireguard.
# make -j$(nproc)
# make tarxz-pkg
# tar tvf linux-5.18.14-x86.tar.xz
drwxr-xr-x root/root 0 2022-07-28 07:36 boot/
-rw-r--r-- root/root 133768 2022-07-28 07:36 boot/config-5.18.14
-rw-r--r-- root/root 11202432 2022-07-28 07:36 boot/vmlinuz-5.18.14
-rwxr-xr-x root/root 73921096 2022-07-28 07:36 boot/vmlinux-5.18.14
-rw-r--r-- root/root 5670638 2022-07-28 07:36 boot/System.map-5.18.14
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/
-rw-r--r-- root/root 331 2022-07-28 07:36 lib/modules/5.18.14/modules.order
-rw-r--r-- root/root 862 2022-07-28 07:36 lib/modules/5.18.14/modules.alias
-rw-r--r-- root/root 11704 2022-07-28 07:36 lib/modules/5.18.14/modules.builtin
-rw-r--r-- root/root 12 2022-07-28 07:36 lib/modules/5.18.14/modules.symbols.bin
-rw-r--r-- root/root 106167 2022-07-28 07:36 lib/modules/5.18.14/modules.builtin.modinfo
-rw-r--r-- root/root 1528 2022-07-28 07:36 lib/modules/5.18.14/modules.alias.bin
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/netfilter/
-rw-r--r-- root/root 11256 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/netfilter/xt_nat.ko
-rw-r--r-- root/root 7200 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/netfilter/xt_LOG.ko
-rw-r--r-- root/root 31152 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/netfilter/nf_log_syslog.ko
-rw-r--r-- root/root 6216 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/netfilter/xt_mark.ko
-rw-r--r-- root/root 11440 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/netfilter/xt_addrtype.ko
-rw-r--r-- root/root 7360 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/netfilter/xt_MASQUERADE.ko
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/ipv4/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/ipv4/netfilter/
-rw-r--r-- root/root 9264 2022-07-28 07:36 lib/modules/5.18.14/kernel/net/ipv4/netfilter/iptable_nat.ko
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/fs/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/fs/efivarfs/
-rw-r--r-- root/root 20504 2022-07-28 07:36 lib/modules/5.18.14/kernel/fs/efivarfs/efivarfs.ko
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/drivers/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/drivers/thermal/
drwxr-xr-x root/root 0 2022-07-28 07:36 lib/modules/5.18.14/kernel/drivers/thermal/intel/
-rw-r--r-- root/root 20984 2022-07-28 07:36 lib/modules/5.18.14/kernel/drivers/thermal/intel/x86_pkg_temp_thermal.ko
-rw-r--r-- root/root 0 2022-07-28 07:36 lib/modules/5.18.14/modules.devname
-rw-r--r-- root/root 10944 2022-07-28 07:36 lib/modules/5.18.14/modules.builtin.alias.bin
-rw-r--r-- root/root 49 2022-07-28 07:36 lib/modules/5.18.14/modules.symbols
-rw-r--r-- root/root 975 2022-07-28 07:36 lib/modules/5.18.14/modules.dep.bin
-rw-r--r-- root/root 340 2022-07-28 07:36 lib/modules/5.18.14/modules.dep
lrwxrwxrwx root/root 0 2022-07-28 07:36 lib/modules/5.18.14/build -> /usr/src/linux-5.18.14
-rw-r--r-- root/root 89 2022-07-28 07:36 lib/modules/5.18.14/modules.softdep
lrwxrwxrwx root/root 0 2022-07-28 07:36 lib/modules/5.18.14/source -> /usr/src/linux-5.18.14
-rw-r--r-- root/root 14623 2022-07-28 07:36 lib/modules/5.18.14/modules.builtin.bin
Мдя...
Вот и всё.
Больше нельзя установить CRUX 3.7 в чистом виде на диск размером 1,000,000,000 байт чтобы запускать его на VDS.
Придётся делать обрезание пингвину! Например, мы можем выиграть немного свободного места, если затюним файловую систему, ну хотя бы tune2fs -m 1 /dev/sdb1
— зарезервируем для root'а 1% свободного пространства, вместо 5%.
Отключать насовсем этот резерв нельзя, иначе вы не сможете даже зайти по ssh, когда логи в /var/log съедят всё оставшееся место на диске.
# umount /mnt
# tune2fs -m 1 /dev/sdb1
# tune2fs -m 1 /dev/sdc1
CRUX 3.6
mount /dev/sdb1 /mnt
# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 920M 766M 129M 86% /mnt
CRUX 3.7
# mount /dev/sdc1 /mnt/
# df -h /mnt/
Filesystem Size Used Avail Use% Mounted on
/dev/sdc1 920M 838M 57M 94% /mnt
Иии... Ядро по-прежнему нельзя установить, недостаточно места.
Другой вариант, немного покромсать файлы ядра, ведь на самом деле для работы системы нам нужно только само ядро vmlinuz и папка /lib.
Давайте сделаем так и извлечём только эти файлы.
# tar xvf linux-5.18.14-x86.tar.xz -C /mnt boot/vmlinuz-5.18.14 lib/
После установки ядра, оставшееся место для CRUX 3.6
# df -h /mnt/
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 920M 777M 80M 91% /mnt
И оставшееся место для CRUX 3.7
# df -h /mnt
Filesystem Size Used Avail Use% Mounted on
/dev/sdc1 920M 849M 6.9M 100% /mnt
Загрузчик, финальная настройка системы!
# mount /dev/sdb1 /mnt/
# mount --bind /dev /mnt/dev
# mount -t proc proc /mnt/proc
# mount -t sysfs none /mnt/sys
# chroot /mnt/ /bin/bash
# localedef -i en_US -f UTF-8 en_US.UTF-8
# passwd
# grub-install /dev/sdb
# grub-mkconfig -o /boot/grub/grub.cfg
# umount -R /mnt
Аналогично делаем с /dev/sdc1, где у нас установлен CRUX 3.7
# mount /dev/sdc1 /mnt
# mount --bind /dev /mnt/dev
# mount -t proc proc /mnt/proc
# mount -t sysfs none /mnt/sys
# chroot /mnt/ /bin/bash
# localedef -i en_US -f UTF-8 en_US.UTF-8
# passwd
New password:
Retype new password:
passwd: password updated successfully
# grub-install /dev/sdc
Installing for i386-pc platform.
Installation finished. No error reported.
# grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.18.14
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done
Не забудьте в grub.cfg заменить все /dev/sdb и /dev/sdc устройства на /dev/sda т.к. загрузка будет происходить именно с /dev/sda.
В финале, у нас осталось 1.6 мегабайт свободного пространства после установки CRUX 3.7 на 1,000,000,000-байтный диск!
# df -h /mnt/
Filesystem Size Used Avail Use% Mounted on
/dev/sdc1 920M 855M 1.6M 100% /mnt
Для работы системы это не критично, всё свободное место съедят логи в /var/log, а система продолжит работу.
И в завершении всего, я выложил образы виртуальных машин обновлённых версий CRUX 3.6 и CRUX 3.7
>>> Скачать CRUX 3.6 IMG (1,000,000,000b)
>>> Скачать CRUX 3.7 IMG (1,000,000,000b)
Логин root пароль toor, чтобы вы могли просто скачать образы и пощупать систему CRUX GNU/Linux вживую!
Раз в несколько лет я пытаюсь осилить нормальный дистрибутив, но в итоге всегда возвращаюсь к CRUX.
Забавно, как на моём ноутбуке, i7-11-чего-то-там, 40GB RAM и 512GB NVMe, самый обычный терминал запускается секунду-две, дело было на Fedora/Gnome42. Пробовал дефолтную Ubuntu, но никак не могу привыкнуть к интерфейсу...
О! https://github.com/grassmunk/Chicago95
То, что доктор прописал. Настроив хоткеи под себя, этим наконец можно пользоваться. Посмотрим, как скоро я вернусь обратно на CRUX/FVWM, но пока остаюсь на Ubuntu/XFCE+Chicago95. Так!
>>> Просмотр (3440x1440, 696 Kb)
Не знаю какой чёрт меня дёрнул, но решил обмазаться мейнстримом, установил последнюю Fedora + Gnome 3 на свой ноутбук.
10 из 10, господи, 10 из 10!!!
Последний раз когда я ставил гном с момента его появления на свет, выглядил он весьма кринжово, когда слева надо триггернуть панель быстрого запуска приложений, а справа надо было триггернуть список рабочих столов, т.е. помимо того, что надо жмякнуть в «Обзор», потом надо было знатно ещё помышевозить, а переключение между приложениями вообще было непонятно как организовано.
А что сейчас? Я просто вожу по тачпаду тремя пальцами вниз-вверх чтобы запустить приложение, а влево-право переключаюсь между рабочими столами. При этом я могу вниз провести пальцами один раз, а затем начать печатать имя приложения чтобы его запустить, всё упрощено донельзя, и для домохозяек и для профессиональных пользователей.
У меня возникло ощущение как будто бы я этот гном делал, он настолько стал интуитивно понятный и простой... Потому что если бы я этот гном делал, я бы его сделал именно таким, какой он есть сейчас, это гениально, это просто нечто, слов нет какая федора с дефолтным гномом классная!
Даже если сейчас в процессе использования всплывут какие-то огрехи, всё равно все плюсы интерфейса перекрывают любые недостатки, я готов простить гному даже если его плазма будет падать каждые 10 минут. Вот так вот!
Я закончил.
Ну вот как, когда даже такой параметр как IP, злодей может менять «на лету». В данном случае конечно же имеется ввиду IPv6, но всё же. Так же, подсетями блочить? Ну нет, там же этими же подсетями и раздают эти адреса направо и налево.
По сути, вообще вариантов не остаётся, кроме как создавать свой внутренний идентификатор (логин) пользователя и фильтровать пользователей по нему. Я бы очень хотел оставить анонимусов, но похоже их эпоха прошла.
Здравствуйте, мои маленькие психологически зрелые личности!
В свободное от работы время, в своё удовольствие, когда никому ничего не должен, когда нет кредитов и долгов, никаких обязательств перед кем-либо, когда приходишь домой, а дома тишина, чистота, покой и умиротворение, и никто слова тебе поперёк не скажет, — я занимаюсь разработкой своего проекта, сайта, на базе которого можно создавать другие сайты и управлять ими.
Исходный код вы можете скачать по ссылке http://www.netboot.ru/latest.tar, сейчас это сугубо-черновой вариант только чтобы продемонстировать рабочий прототип, оценить качество кода и может быть внести своё предложение по развитию.
Проверить как оно работает вживую вы можете на сайте http://www.netboot.ru/blog/, где пока на время тестирования вы можете свободно добавлять и редактировать любые сообщения.
Как я писал ранее, я не осилил ООП, поэтому проект написан в олдскульном стиле (или депрекейтед, уж кому как), с использованием исключительно простых функций, но при этом без использования глобальных переменных! Я большой перфекционист и строг прежде всего к самому себе в плане качества работы и кода, поэтому старался писать правильно.
Так например, у меня заведено в правилах, что каждая, подчёркиваю, _каждая_ функция возращает false, всегда! Чтобы функция вернула нужный нам результат, мы должны сами, подчёркиваю, _сами_, через условия добывать этот результат. Только так. В противном случае всегда будет false, и функции, которые друг-друга вызывают, получают false и отвечают тоже false, и клиент получает ошибку. С этим у меня очень строго.
Но не смотря на это, функции всё ещё поделены логически на отдельные пространства имён, то есть, все функции, которые работают с базой данных, начинаются с префикса db_, все функции, которые работают с сессиями, начинаются с префикса session_ и т.д. Соответсвенно такие списки функций я выделил в отдельные файлы, которые назвал не-классами, в ./src/noclasses лежат .noclass.php файлики.
Весь, целиком и полностью весь проект написан на функциях и ничего нигде «случайно» не происходит. Так, если вызвать php-файл напрямую из браузера, то ничего не произойдёт, т.к. там просто объявляются функции!
Проект состоит из /index.php файлика, ./src/noclasses/*.noclass.php функций и ./src/contollers/*.php контроллеров.
В /index.php самой первой вызывается функция:
run($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']);
То есть, по-сути, чтобы сэмулировать какой-то запрос и получить на него ответ, вы можете дёргать эту функцию руками.
Далее в main.noclass.php эта функция обрабатывает запрос и выдаёт ответ.
function run($request_uri, $request_method) {
$route = route($request_uri, $request_method);
$buffer = process($route);
$output = output($buffer);
return false;
}
route() смотрит какой документ запросили и выдаёт контроллер, который должен обработать запрос.
process() запускает заданный контроллер на выполнение, контроллер возвращает ответ, сгенерированную страничку например.
output() просто отдаёт ответ клиенту.
Функция route() требует доработки, т.к. каждый запрашиваемый документ проверяется вручную, а нам нужно реализовать динамический роутинг, который будет по списку смотреть маршрут и выдавать контроллер. //TODO в общем.
function route($request_uri, $request_method) {
$request_path = strtok($request_uri, '?');
$request = explode('/', $request_path);
$require = false;
if (end($request) == '') {
if ($request[1] == '') {
$require = 'index.php';
return $require;
}
}
return false;
}
Функция process() занимается вызовом котроллера.
function process($route) {
if ($route == false) {
echo 'kernel panic: controller not found';
return false;
}
$request = $route['request'];
$require = $route['require'];
ob_start();
$exec = (@include($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'controllers' . DIRECTORY_SEPARATOR . $require));
$ob_buffer_length = ob_get_length();
$ob_buffer = ob_get_contents();
ob_end_clean();
if ($ob_buffer_length > 0) {
echo 'kernel panic: buffer overflow outside of request() function in ' . $require;
return false;
}
if ($exec == false) {
echo 'kernel panic: failed to execute ' . $require;
return false;
}
if (function_exists('request')) {
$exec = request($request['request_uri'], $request['request_method'], $request['request']);
if ($exec == false) {
echo 'kernel panic: request() function returned false in ' . $require;
return false;
}
return $exec;
}
else {
echo 'kernel panic: request() function is not defined in ' . $require;
return false;
}
return false;
}
Вы видите, что, если php-скрипт что-то выводит вне вызываемой функции, это приводит к «панике»: kernel panic: buffer overflow outside of request()
Каждый контроллер обязан содержать функцию request(), которая уже обрабатывает запрос и выдаёт ответ.
Вот пример такого контроллера, который обрабатывает GET и POST запросы и выводит ответ.
function request($request_uri, $request_method, $request) {
if ($request_method == 'GET') {
return get_index();
}
if ($request_method == 'POST') {
return post_index();
}
return false;
}
function get_index() {
return 'Hello World!';
}
function post_index() {
return 'Hello World!';
}
Например, мы хотим отрисовать шаблон, тогда функция get_index будет выглядить так.
function get_index() {
$var = array(
'title' => 'Welcome!',
'body' => 'Hello world!'
);
$view = view('index.view-get-request', $var);
return $view;
}
И шаблон будет загружен из файла ./themes/localhost.localdomain/index.view-get-request.php
Как вы видите, не смотря на то, что код полностью написан на функциях, я бы сказал, что он напоминает чем-то ООП: на функциях тоже можно писать хорошо!
всем привет я пишу сайт на пхп четыре (из-за pdo это пока не получается, поэтому если есть замена pdo для работы с различными бд — подскажите)
главная фича моего движка в простой кодовой базе, в которой разберётся любой начинающий программист на html, css и php
есть поддержка виртуальных хостов. один движок может обслуживать сколько угодно сайтов, у каждого сайта может быть свой индивидуальный дизайн, при этом у них единая база данных с сообщениями и пользователями. например, на одном движке можно вести несколько сайтов, а затем «на лету» их смержить в один, объеденив область видимости нескольских сайтов в один, либо же наоборот, если проект разрастается и условная тема про собачек на сайте котиков набирает популярность — сайт можно раздробить на два, один про кошечек, второй про собачек, при этом пользователям не придётся создавать новые аккаунты на втором сайте.
как уже сказал, у каждого хоста может быть свой индивидуальный дизайн, то есть пользователь вообще не будет знать, что сайт про кошечек и сайт про собачек — это один и тот-же сайт. он увидит перед собой два разных сайта, у каждого своя область видимости в базе данных и дизайн.
все сообщения на сайте — как статьи на википедии, или как сообщения на ЛОРе, могут редактироваться сколько угодно раз и хранить всю историю изменений. весь ключевой вопрос лишь в том, способен ли выдержать SQLite такую нагрузку, или же придётся смотреть в сторону другой базы данных???
пользователи могут создавать сколько угодно аккаунтов и логиниться под разными аккаунтами, а затем переключаться между ними. считаю это прикольным.
у меня своя собственная реализация сессий, которая никак не связана со встроенными сессиями на пхп и никак их не использует. то есть session_*(); и $_SESSION не задействуются. моя реализация позволяет более тонко контролировать все нюансы, например, не создавать пустую сессию «в холостую», или например точно определить, что в папке на диске достаточно места для хранения данных сессии.
вот пример базы данных для сообщений. они хранят всю историю изменений.
CREATE TABLE IF NOT EXISTS 'post'
(
'id' INTEGER PRIMARY KEY,
'domain' NVARCHAR(255) DEFAULT NULL,
'sub_reply' INTEGER DEFAULT NULL,
'date_created' DATETIME DEFAULT CURRENT_TIMESTAMP,
'date_modified' DATETIME DEFAULT NULL,
'flags' NVARCHAR(200) DEFAULT NULL
);
CREATE TABLE IF NOT EXISTS 'post_history'
(
'id' INTEGER PRIMARY KEY,
'sub_post' INTEGER NOT NULL,
'ref_text' INTEGER NOT NULL,
'date_created' DATETIME DEFAULT CURRENT_TIMESTAMP,
'date_modified' DATETIME DEFAULT NULL
);
CREATE TABLE IF NOT EXISTS 'post_text'
(
'id' INTEGER PRIMARY KEY,
'text' TEXT DEFAULT NULL,
'text_headers' TEXT DEFAULT NULL
);
сам текст сообщений хранится отдельно в третьей таблице, это сделано потому, что у каждой базы данных (конкретно у MySQL и PostgreSQL) на этот счёт разное мнение. кто-то хранит TEXT и BLOB далеко за пределами основной таблицы, чтобы минимизировать нагрузку при выборке из базы, а кто-то хранит там же рядышком. правильнее будет хранить TEXT отдельно. поэтому храню.
я не осилил ООП и не смог написать на классах, поэтому я писал на функциях, и я их назвал неклассами.
в папочке ./src/noclass/ у меня лежат следующие неклассы.
database.noclass.php:
<?php
function db_directory_sqlite() {
return dirname($_SERVER['DOCUMENT_ROOT']) . '/db';
}
function db_connect($db_dsn = null, $db_username = null, $db_password = null, $db_attributes = null) {
$db = false;
if (strpos($db_dsn, 'sqlite:') == 0) {
$db_file = substr($db_dsn, strlen('sqlite:'));
if ($db_file == ':memory:') {
$db = true;
}
elseif (is_writeable(db_directory_sqlite())) {
$db = true;
}
}
if ($db == false) {
return false;
}
$db = db_connect_retry($db_dsn, $db_username, $db_password, $db_attributes);
return $db;
}
function db_connect_retry($db_dsn, $db_username, $db_password, $db_attributes) {
$db = false;
while ($db == false) {
try {
$db = new PDO($db_dsn, $db_username, $db_password, $db_attributes);
}
catch (Exception $e) {
if (stripos($e->getMessage(), 'DATABASE IS LOCKED')) {
usleep(50000);
continue;
}
return false;
}
}
return $db;
}
function db_open_sqlite_in_memory() {
$db_file = false;
$db_dsn = 'sqlite::memory:';
$db = db_connect($db_dsn);
return $db;
}
function db_open_sqlite($db_file) {
if ($db_file == ':memory:') {
$db = db_open_sqlite_in_memory();
return $db;
}
$db_dsn = 'sqlite:' . $db_file;
$db = db_connect($db_dsn);
return $db;
}
function db_open($db_dsn) {
$db = db_open_sqlite($db_dsn);
return $db;
}
function db_exec($db, $query_string) {
$query = $db->exec($query_string);
return $query;
}
function db_query($db, $query_string) {
$query = $db->query($query_string);
return $query;
}
function db_run($db, $query_string, $query_args = false) {
if ($query_args == false) {
$query = db_query($db, $query_string);
return $query;
}
$query = $db->prepare($query_string);
$query->execute($query_args);
return $query;
}
function db_begin_transaction($db) {
$query = $db->beginTransaction();
return $query;
}
function db_is_transaction($db) {
$query = $db->inTransaction();
return $query;
}
function db_rollback($db) {
$query = $db->rollBack();
return $query;
}
function db_commit($db) {
$query = $db->commit();
return $query;
}
function db_last_id($db) {
$query = $db->lastInsertId();
return $query;
}
function db_insert($db, $table, $values) {
$keys = array_keys($values);
$values = array_values($values);
$columns = array();
foreach ($keys as $item) {
$columns[] = "'$item'";
}
$columns = implode(',', $columns);
$placeholders = array();
foreach ($keys as $item) {
$placeholders[] = "?";
}
$placeholders = implode(',', $placeholders);
$query = "INSERT INTO $table ($columns) VALUES ($placeholders);";
$query = db_run($db, $query, $values);
return $query;
}
function db_update($db, $table, $value, $where) {
$collection = array_merge($value, $where);
$collection = array_values($collection);
$fields = array();
foreach ($value as $item => $data) {
$fields[] = "$item = ?";
}
$fields = implode(',', $fields);
$places = array();
foreach ($where as $item => $data) {
$places[] = "$item = ?";
}
$places = implode(' AND ', $places);
$query = "UPDATE $table SET $fields WHERE $places;";
$query = db_run($db, $query, $collection);
return $query;
}
function db($db_name) {
$db_file = db_directory_sqlite() . DIRECTORY_SEPARATOR . $db_name;
$db = db_open($db_file);
return $db;
}
post.noclass.php:
<?php
function post_insert($text_headers, $text, $replyto = false) {
$db = db('example.db');
if ($db == false) {
return false;
}
db_begin_transaction($db);
if (db_post_insert($db, $text_headers, $text, $replyto)) {
db_commit($db);
return true;
}
db_rollback($db);
return false;
}
function db_post_insert($db, $text_headers, $text, $replyto = false) {
if ($replyto == false) {
$id = db_post_insert_id($db);
if ($id == false) {
return false;
}
}
else {
$replyto = db_post_select_id_single($db, $replyto);
if ($replyto == false) {
return false;
}
else {
$id = db_post_insert_id($db);
if ($id == false) {
return false;
}
}
}
if (db_post_insert_post($db, $id, $replyto)) {
$ref_text = db_post_insert_post_text($db, $text_headers, $text);
if ($ref_text == false) {
return false;
}
if (db_post_insert_post_history($db, $id, $ref_text)) {
return $id;
}
}
return false;
}
function db_post_insert_id($db) {
$value = array(
'id' => null
);
db_insert($db, 'post', $value);
return db_last_id($db);
}
function db_post_select_id_single($db, $id) {
$value = array(
'id' => $id
);
$query = 'SELECT id FROM post WHERE id = :id;';
$query = db_run($db, $query, $value);
$row = $query->fetch();
return ($row == false) ? false : $row['id'];
}
function db_post_insert_post($db, $id, $replyto = false) {
$date_created = date('Y-m-d H:i:s', time());
$date_modified = null;
$search = array(
'id' => $id
);
$entry = array(
'id' => null,
'domain' => null,
'sub_reply' => $replyto,
'date_created' => $date_created,
'date_modified' => $date_modified,
'flags' => null
);
// remove false, null and other zero-values from entry
$entry = array_filter($entry);
if (db_update($db, 'post', $entry, $search)) {
return $id;
}
return false;
}
function db_post_insert_post_text($db, $text_headers, $text) {
if ($text_headers == false) {
//nothing to do -- skip headers
}
else {
$text_headers = serialize($text_headers);
}
$entry = array(
'id' => null,
'text' => $text,
'text_headers' => $text_headers
);
// remove false, null and other zero-values from entry
$entry = array_filter($entry);
if (db_insert($db, 'post_text', $entry)) {
return db_last_id($db);
}
return false;
}
function db_post_insert_post_history($db, $sub_post, $ref_text) {
$date_created = date('Y-m-d H:i:s', time());
$date_modified = null;
$entry = array(
'id' => null,
'sub_post' => $sub_post,
'ref_text' => $ref_text,
'date_created' => $date_created,
'date_modified' => $date_modified
);
// remove false, null and other zero-values from entry
$entry = array_filter($entry);
if (db_insert($db, 'post_history', $entry)) {
return db_last_id($db);
}
return false;
}
function db_post_select_count($db) {
$query = db_query($db, 'SELECT COUNT(*) as sizeof FROM post;');
$row = $query->fetch();
return $row['sizeof'];
}
function post_update($id, $text_headers, $text) {
$db = db('example.db');
if ($db == false) {
return false;
}
db_begin_transaction($db);
if (db_post_update($db, $id, $text_headers, $text)) {
db_commit($db);
return true;
}
db_rollback($db);
return false;
}
function db_post_update($db, $id, $text_headers, $text) {
$id = db_post_select_id_single($db, $id);
if ($id == false) {
return false;
}
if (db_post_update_post($db, $id)) {
$ref_text = db_post_insert_post_text($db, $text_headers, $text);
if ($ref_text == false) {
return false;
}
if (db_post_insert_post_history($db, $id, $ref_text)) {
return $id;
}
}
return false;
}
function db_post_update_post($db, $id) {
$date_created = null;
$date_modified = date('Y-m-d H:i:s', time());
$search = array(
'id' => $id
);
$entry = array(
'id' => null,
'domain' => null,
'sub_reply' => null,
'date_created' => $date_created,
'date_modified' => $date_modified,
'flags' => null
);
// remove false, null and other zero-values from entry
$entry = array_filter($entry);
if (db_update($db, 'post', $entry, $search)) {
return $id;
}
return false;
}
function db_post_select_id($db, $id = false) {
if ($id == false) {
return false;
}
$value = array(
'id' => $id
);
$query = '
SELECT * FROM post
INNER JOIN post_history AS initial ON (initial.sub_post = post.id AND initial.id = (SELECT id FROM post_history WHERE sub_post = post.id ORDER BY id ASC LIMIT 1))
INNER JOIN post_history AS current ON (current.sub_post = post.id AND current.id = (SELECT id FROM post_history WHERE sub_post = post.id ORDER BY id DESC LIMIT 1))
INNER JOIN post_text ON post_text.id = current.ref_text
WHERE post.id = :id
';
$query = db_run($db, $query, $value);
$row = $query->fetch();
$row = post_row($row);
return $row;
}
function db_post_select_page($db, $page = false, $limit = 10) {
$pages = (db_post_select_count($db) / $limit);
$pages = ceil($pages);
if ($page == false) {
$page = $pages;
}
elseif ($page > $pages) {
$page = $pages;
}
elseif ($page < 1) {
$page = $pages;
}
$offset = ($page - 1) * $limit;
// should I make it more stronger?
// escape offset and limit
$query = '
SELECT * FROM post
INNER JOIN post_history AS initial ON (initial.sub_post = post.id AND initial.id = (SELECT id FROM post_history WHERE sub_post = post.id ORDER BY id ASC LIMIT 1))
INNER JOIN post_history AS current ON (current.sub_post = post.id AND current.id = (SELECT id FROM post_history WHERE sub_post = post.id ORDER BY id DESC LIMIT 1))
INNER JOIN post_text ON post_text.id = current.ref_text
ORDER BY id DESC LIMIT ' . $limit . ' OFFSET ' . $offset . ';
';
$query = db_query($db, $query);
$array = array();
while ($row = $query->fetch()) {
$array[] = post_row($row);
}
return $array;
}
function post_row($row) {
if ($row == false) {
return false;
}
if ($row['date_created'] == null) {
$row['date_created'] = '(unavailable)';
}
if ($row['date_modified'] == null) {
$row['date_modified'] = '(unavailable)';
}
if (empty($row['text_headers'])) {
$row['text_headers'] = array();
}
else {
$row['text_headers'] = unserialize($row['text_headers']);
}
if (empty($row['text_headers']['title'])) {
$row['text_headers']['title'] = '';
}
return $row;
}
function post_escape($text) {
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
$text = nl2br($text);
return $text;
}
function post_input_filtered($text) {
$text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
return $text;
}
function post_text_filtered($text) {
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
return $text;
}
session.noclass.php
<?php
function session_directory() {
return dirname($_SERVER['DOCUMENT_ROOT']) . DIRECTORY_SEPARATOR . 'db' . DIRECTORY_SEPARATOR . 'sess';
}
function session_open($session_name = 'ident') {
$session_id = session_open_if_cookie_is_set($session_name);
if ($session_id == false) {
$session_id = session_new($session_name);
}
return $session_id;
}
function session_open_if_cookie_is_set($session_name = 'ident') {
if (isset($_COOKIE[$session_name])) {
$session_id = $_COOKIE[$session_name];
if (strlen(str_replace(array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'), '', $session_id)) > 0) {
$session_id = session_new($session_name);
}
return $session_id;
}
return false;
}
function session_load($session_id) {
$session_file = session_directory() . DIRECTORY_SEPARATOR . $session_id;
$session_data = false;
if ($fp = @fopen($session_file, 'r')) {
flock($fp, LOCK_SH);
$session_data = fread($fp, filesize($session_file));
$session_data = unserialize($session_data);
flock($fp, LOCK_UN);
fclose($fp);
}
if (is_array($session_data)) {
return $session_data;
}
return array();
}
function session_save($session_id, $session_data = array()) {
$session_file = session_directory() . DIRECTORY_SEPARATOR . $session_id;
$session_data = serialize($session_data);
if ($fp = @fopen($session_file, 'w+')) {
flock($fp, LOCK_EX);
$bytes_written = fwrite($fp, $session_data);
flock($fp, LOCK_UN);
fclose($fp);
}
return $bytes_written;
}
function session_new($session_name) {
if (headers_sent()) {
return false;
}
$session_id = bin2hex(session_random_bytes(8));
$cookie_lifetime = 0;
$cookie_path = '/';
$cookie_domain = '';
$cookie_secure = false;
$cookie_httponly = false;
if (setcookie($session_name, $session_id, $cookie_lifetime, $cookie_path, $cookie_domain, $cookie_secure, $cookie_httponly) == false) {
return false;
}
return $session_id;
}
function session_random_bytes($length = 32) {
$random_bytes = '';
for ($i = 0; $i < $length; $i++) {
$random_bytes .= chr(rand(0, 255));
}
return $random_bytes;
}
function session() {
$id = session_open();
if ($id == false) {
return false;
}
$session = session_load($id);
return $session;
}
вот вам небольшая инструкция как использовать сессии
вы просто делаете $session = session(); и создаётся новая сессия и в переменную $session загружается массив со всеми данными сессии.
если вы хотите что-то сохранить в сессию, то вы должны проделать все действия вручую:
// создаём новую сессию
// в $id помещается идентификатор сессии, ну типа PHPSESSID
$id = session_open();
// загружаем данные сессии в переменную $session
// можно для этого использовать $_SESSION но я не хочу и не буду
$session = session_load($id);
// создаём в $session приветствие
$session = array('greeting' => 'hello world!');
// сохраняем данные сессии, за вас это никто не сделает
session_save($id, $session);
есть такой забавный момент, когда мы не хотим создавать сессию, если у пользователя её нету. для этого есть функция session_open_if_cookie_is_set();, которая запускает сессию только при наличии куки.
в целом моя реализация сессий лучше пхпшной т.к. она не создаёт пустых файлов!!! каждый момент вы контролируете сами!!!
теперь давайте я вам расскажу про сообщения а-ля википедия или лор.
для отправки сообщения я делаю так:
$headers = array(
'title' => 'заголовок письма'
);
$content = 'текст письма';
post_insert($headers, $content);
как вы знаете у сообщения есть не только его содержимое, не только сам текст сообщения. у сообщения есть мета-данные, такие как заголовок, тэги, ну ещё что-нибудь может быть. поэтому все эти мета-данные помещаются в отдельный массив.
затем при выборке сообщения из базы мы можем сравить, сделать diff не только на сам текст сообщения, но и на все заголовки тоже сделать diff и увидеть различия между двумя версиями сообщения включая всю мета-информацию, — заголовки, теги. теперь вы понимаете почему я решил так сделать.
функция post_insert(); вернёт просто true в случае узбека. иначе false.
для того, чтобы отредактировать сообщение, есть функция post_update();, но первым параметром ещё нужно указать ID сообщения.
например мы только что добавили сообщение, его ID 1, теперь мы хотим его отредактировать.
$id = '1';
$headers = array(
'title' => 'заголовок письма (отредактировано)'
);
$content = 'исправленный текст письма';
post_update($id, $headers, $content);
и теперь в базу будет сохранена новая версия сообщения.
выполняем sqlite example.db .dump и смотрим
INSERT INTO post VALUES(1,NULL,NULL,'2022-07-17 06:24:55','2022-07-17 06:25:26',NULL);
INSERT INTO post_history VALUES(1,1,1,'2022-07-17 06:24:55',NULL);
INSERT INTO post_history VALUES(2,1,2,'2022-07-17 06:25:26',NULL);
INSERT INTO post_text VALUES(1,'текст письма','a:1:{s:5:"title";s:31:"заголовок письма";}');
INSERT INTO post_text VALUES(2,'исправленный текст письма','a:1:{s:5:"title";s:64:"заголовок письма (отредактировано)";}');
по факту сообщение одно, а ревизии у него две! так-то!
для того, чтобы прочитать сообщение в массив мы подключаемся к базе данных и выполняем одну функцию, указав ID сообщения
$db = db('example.db');
if ($db == false) {
return false;
}
$post = db_post_select_id($db, $_GET['id']);
var_dump($post);
для того, чтобы вывести страницу со списком сообщений есть функция db_post_select_page($db, $_GET['page']);
в целом мой код будет очень хорошо документирован, но это чуть попозже, пока только реализация.
мой код написан очень качественно на совесть, писал для себя.
очень скоро будет релиз и я создаю отдельный сайт посвящённый своей цмс на пхп четыре. оцените качество кода, насколько он красив и хорош, и очень строгий!
главный вопрос — выдержит ли такая структура базы данных на SQLite нагрузку с бесконечным редактированием сообщений???
На сайте название которого нельзя произносить вслух люди массово жалуются на сброс URL.
Вот я сейчас если сделаю сайт, там зарегистрируются все мои друзья с ЛОРа, мой сайт тоже окажется «вне закона»?
Или любой кто будет использовать опен-сорц(!) движок ЛОРа окажется вне закона?
Может тогда стоит добавить новое правило?
9999.1) Нельзя форкать ЛОР
А опен-сорц, он для кого надо опен-сорц.
Я просто хочу разобраться в политике администрации ЛОРа. Где проходит граница? Ну просто уточнили бы, чтобы люди не мучались, за что их собственно минусуют.
следующие → |