LINUX.ORG.RU

Сообщения vbr

 

Максимально повторяемая страница на разных браузерах

 

Я хочу сделать страницу, которая будет выглядеть максимально похоже на разных браузерах. Идеал - попиксельная идентичность. Понимаю, что идеала не достичь, но хочу достичь что могу.

Ширина и высота у страницы фиксированные.

Шрифты я использую свои.

На что ещё нужно обратить внимание, по крайней мере из очевидного?

Я так понимаю, применять что-то вроде font-size: xx-large не стоит, т.к. это не соответствует конкретному кеглю и лучше применять что-то вроде font-size: 30px.

vbr
()

Как правильно использовать C без стандартной библиотеки?

 ,

Хочу писать на C для МК, но так, чтобы ни единого байта не было в бинарнике, не от моего кода.

В целом я понимаю, как это всё собрать и слинковать. Вопрос больше в том, что компилятор C в моём понимании генерирует код, рассчитывая на определённый рантайм, который я у него хочу забрать. К примеру я слыхал, что компилятор может генерировать вызовы функций вроде memcpy, если посчитает нужным. Также я не очень хорошо представляю, что происходит до вызова main и насколько это важно.

Также развитие этого вопроса - тот же вопрос про C++.

vbr
()

Не могу собрать Qt для кросс-компиляции

 ,

Хочу написать приложение, которое будет работать на arm девайсе. Документации не нашёл, делаю по крохам информации, которую нашёл, но ничего не получилось.

Во-первых нужно собрать Qt для хоста.

Хост у меня дебиан. Ставлю пакеты cmake gcc g++ mesa-common-dev ninja-build perl. Собираю командами

../qt-everywhere-src-6.4.3/configure -prefix /mnt/data/qt-host -submodules qtbase
cmake --build . --parallel 4
cmake --install .

Это у меня получилось.

Далее нужно собрать Qt для таргета. Таргет у меня это какая-то китайская плата с i.MX8MM. Есть rootfs для неё.

Первая проблема в том, что не понятно, где брать компилятор. Я поставил таким образом:

dpkg --add-architecture arm64
apt-get update
apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi

Также пробовал вариации с --add-architecture arm и gnueabhf. Не знаю, чем они отличаются и как понять, какой мне надо.

Далее написал файл imx8mm.cmake со следующими строчками:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++)
set(CMAKE_SYSROOT ${INPUT_sysroot})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

и пытаюсь сконфигурировать Qt командой

/mnt/data/qt-everywhere-src-6.4.3/configure \
  -prefix /opt/qt \
  -extprefix /mnt/data/qt-embedded \
  -qt-host-path /mnt/data/qt-host \
  -sysroot /mnt/data/rootfs-ok8mm \
  -submodules qtbase \
  -nomake examples -nomake tests \
  -- \
  -DCMAKE_TOOLCHAIN_FILE=/home/build/imx8mm.cmake

Это всё кончается ошибкой

ERROR: The OpenGL functionality tests failed! You might need to modify the OpenGL package search path by setting the OpenGL_DIR CMake variable to the OpenGL library's installation directory.

Я не знаю, где посмотреть точно какая ошибка ему помешала.

В файле CMakeError.log есть миллион ошибок, но в том числе одна, которая мне кажется важной и которую я не знаю, как решить:

: && /usr/bin/arm-linux-gnueabi-gcc --sysroot=/mnt/data/rootfs-ok8mm -DCHECK_FUNCTION_EXISTS=XOpenDisplay -fPIE -pie CMakeFiles/cmTC_d6b57.dir/CheckFunctionExists.c.o -o cmTC_d6b57  /mnt/data/rootfs-ok8mm/usr/lib/libX11.so  /mnt/data/rootfs-ok8mm/usr/lib/libXext.so  /mnt/data/rootfs-ok8mm/usr/lib/libGLESv2.so  /mnt/data/rootfs-ok8mm/usr/lib/libEGL.so && :
/mnt/data/rootfs-ok8mm/usr/lib/libX11.so: file not recognized: file format not recognized
collect2: error: ld returned 1 exit status

Как я понимаю, суть ошибки в том, что компилятор не соответствует плате.

Вот вывод readelf -a /mnt/data/rootfs-ok8mm/usr/lib/libX11.so.6.3.0, может быть он чем-то поможет: https://pastebin.com/raw/5t5dQ2qw

Также ещё вижу такие проблемы: в usr/include платы нет заголовков для EGL, но при этом сами библиотеки в usr/lib есть. Пока до ошибок с EGL не дошёл, планировал их решить установкой пакета EGL в хостовую систему и изменением set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) на BOTH, хотя не уверен, что это правильно.

Может быть я зря на Qt 6 это пытаюсь делать и лучше использовать Qt 5? На плате установлена Qt 5 и есть какие-то примеры на Qt 5. Но, как я понимаю, мне всё равно для своей разработки надо собирать локально версию для кросс-компиляции.

vbr
()

А как в виртуальной машине поддерживать актуальное время?

 ,

Я тут со своей доморощенной виртуализацией экспериментирую. И оказалось, что когда мой ноутбук уснул, в запущенной виртуальной машине время ушло назад на время сна (то бишь не двигалось вперёд). Перезагрузка виртуальной машины проблему решила, но хотелось бы понять, можно ли эту проблему решить другими способами. Я предполагаю, что в запущенном линуксе время отсчитывается средствами процессора, а нужно вероятно вместо этого использовать какие-то аппаратные источники времени (которые, предположительно, в виртуальной машине будут синхронизированы с хостом и будут правильные).

Перемещено hobbit из general

vbr
()

Docker linux/amd64 работает под M1 маком с розеттой

 , ,

Давно хотел проверить, но никак не доходили руки. Вообще говорят, что и в докер десктопе это есть, я не проверял. В целом запустил федору через Virtualization.Framework на M1 макбуке, в ней поставил докер, а также розетту. И теперь:

% docker run --rm -it --platform linux/amd64 debian:11 uname -a
Linux 3ae5494cbd64 6.1.18-200.fc37.aarch64 #1 SMP PREEMPT_DYNAMIC Sat Mar 11 16:03:54 UTC 2023 x86_64 GNU/Linux

Для меня это важно, мне этого давно не хватало. На qemu эмуляция была, но там такая медленная скорость, что было не юзабельно. А тут ничего так, шустренько.

% time docker run --rm -it --platform linux/amd64 debian:11 bash -c "head -c $((1024 * 1024 * 1024)) /dev/zero | sha256sum"
0.02s user 0.02s system 0% cpu 5.759 total

% time docker run --rm -it --platform linux/arm64 debian:11 bash -c "head -c $((1024 * 1024 * 1024)) /dev/zero | sha256sum"
0.03s user 0.02s system 0% cpu 4.770 total
vbr
()

За сколько может грузиться самый быстрый линукс?

 

Если он запускается в виртуалке. Загрузчика вообще нет, сразу ядро и initrd подаётся на вход. Скомпилировать ядро без всего кроме того что надо для виртуалки. Как-то юзерспейс максимально быстро стартануть. Systemd самый быстрый?

У меня сейчас в виртуалке федора с UEFI за несколько секунд грузится. Мне интересно, можно ли это ускорить. Чего она там делает эти несколько секунд - не понятно. dmesg если кому интересно.

vbr
()

Как на старом ядре запустить современный браузер?

 , ,

Имеется китайская плата на i.mx6ull. Китайцы туда поставили китайский линукс на китайском ядре 4.1.15. Браузера там нет. Я хочу туда засунуть веб приложение. Свое ядро более актуальной версии скомпилять пока не вышло. Посоветуйте как быть.

vbr
()

Как разобраться с китайским SoB?

 , ,

Имеется такая плата: OKMX6ULL-C

К ней по шлейфу подключил маленький дисплей. При подаче питания грузится какой-то китайский линукс с демо-программами.

Теперь мне надо из этого сделать что-то своё. Я на raspberry собирал свой линукс, но как тут подступиться, пока не понимаю.

Во-первых я не могу подключиться к нему по UART-у, чтобы работать полноценно, а не на крохотном дисплейчике. На выходных пинах есть UART2, …, UART4. Я подключил USB UART к UART2, но дальше соединиться не смог. К распберри я так подключался.

Судя по схеме UART1 разведён на USB-C выход на этой плате через USB-UART микросхему. Не очень понимаю, для чего это сделано. Можно ли подключить этот выход к компьютеру напрямую? Я боюсь спалить что-нибудь.

Во-вторых я не понимаю, как там вообще устроена загрузка. В распберри просто сд-карта, с неё и грузишься. Тут внутри есть emmc память на 8 гигабайтов. Встроенный линукс грузится именно с неё. Там два раздела, один на 500 MB, там ядро и ещё какой-то файл dtb. На втором разделе корень. В принципе слот для сд-карты есть. Пока грузиться с него не пробовал, т.к. вообще не очень понимаю, что туда сувать.

Ещё есть два раздела mmcblk1boot1 4MiB, mmcblk1boot0 4MiB. Они не монтируются, не знаю, что там на них.

В /etc/issue написано Freescale i.MX Release Distro 4.1.15-2.0.1 \n \l

Моя цель: для начала подключить это всё дело через серийный порт, чтобы можно было с компьютера с ним работать по-человечески. Потом скомпилировать минимальный линукс и загрузиться с него. А потом я уже сам разберусь.

Насколько я понимаю, производитель процессора это NXP, компания нормальная, но саму плату сделали китайцы.

У меня есть два гигабайта какой-то мусорной документации, которую они выслали, но я там ничего не понял. Собственно там толком ничего и нет, самое полезное это распиновка самой платы, остальное - тупо несколько десятков даташитов по всем микросхемам, использованным на плате и какой-то «мануал» с putty.exe и ссылками на китайские форумы, откуда предлагается скачать виртуалбокс. В общем такие мануалы мне не нужны.

Я на распи собирал свой линукс через buildroot. Но там был готовый конфиг и человеческие гайды. Как действовать тут - я пока в затруднении.

vbr
()

Будут ли языки программирования супер высокого уровня?

 ,

В связи с последними разработками в сфере ИИ и рассуждениями о том, заменят ли программистов, интересно было бы подумать о том, насколько можно улучшить производительность.

На мой взгляд за последние лет 30 языки программирования не стали выше уровнем. Если взять тот же Haskell, который в каком-то виде в первый раз появился в 1990 году, то я бы не сказал, что Rust последней версии чем-то категорично его превосходит. В целом примерно одни и те же идеи тусуют в разных пропорциях. Я тут говорю исключительно про то, насколько язык помогает программисту писать код.

Мне интересно, как вообще можно совершить качественный скачок в языках программирования, оставаясь в той же парадигме, т.е. мы не будем рассматривать фантастику вроде того, что ты пытаешься там в чате чего-то объяснять роботу. А мы так же пишем формальный строгий текст латинницей, который преобразуется в машинный код. Но при этом то, что сейчас требует месяца работы, будет требовать трёх дней. Там, где сейчас 10 багов, будет 1 баг.

Предполагать, что что-то придёт взамен тексту, я тоже не буду. Текст доказал свою пользу на протяжении тысячелетий. Думаю, что ничего лучше текста не придумать.

Или же программирование в текущем виде достигло своего апогея и никаких принципиально новых идей уже не стоит ожидать?

vbr
()

Не могу поморгать диодом из C

 , ,

Хочу поморгать диодом без библиотек. В целом сетап описан тут (linux.org.ru). Процессор STM32F030F4P6. Диод подключен, насколько я могу судить, к ноге PA4.

На текущий момент конфигурация такая:

Makefile:

CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
CFLAGS = -mthumb -mcpu=cortex-m0 -O0

.PHONY: all flash

all: app.bin

crt.o: crt.s

app.elf: linker.ld crt.o blink.o
	$(LD) -T linker.ld -o app.elf crt.o blink.o

app.bin: app.elf
	arm-none-eabi-objcopy -O binary $< $@

flash: app.bin
	st-flash --reset write $< 0x8000000

crt.s:

.cpu cortex-m3
.thumb

.word 0x20005000
.word _reset
.thumb_func
_reset:
  bl blink
  b .

linker.ld:

MEMORY {
  FLASH(rx): ORIGIN = 0x08000000, LENGTH = 16K
  RAM (xrw): ORIGIN = 0x20000000, LENGTH = 4K
}

blink.c:

#include <stdint.h>

const uint32_t RCC_BASE = 0x40021000;
const uint32_t GPIOA_BASE = 0x48000000;
const uint32_t RCC_AHBENR_OFFSET = 0x14;
const uint8_t RCC_AHBENR_IOPAEN_BIT = 17;
const uint32_t GPIOx_MODER_OFFSET = 0x00;
const uint8_t GPIOx_MODER_MODE4_BIT_OFFSET = 8;
const uint32_t GPIOx_ODR_OFFSET = 0x14;
const uint8_t GPIOx_ODR_OD4_BIT = 4;

void bit_clear(uint32_t address, uint8_t bit);
void bit_set(uint32_t address, uint8_t bit);
void bit_toggle(uint32_t address, uint8_t bit);

void blink(void) {
  bit_set(RCC_BASE + RCC_AHBENR_OFFSET, RCC_AHBENR_IOPAEN_BIT);
  bit_set(GPIOA_BASE + GPIOx_MODER_OFFSET, GPIOx_MODER_MODE4_BIT_OFFSET);
  bit_set(GPIOA_BASE + GPIOx_ODR_OFFSET, GPIOx_ODR_OD4_BIT);
  volatile uint32_t counter = 0;
  while (1) {
    if (counter % 0x10000 == 0) {
      bit_toggle(GPIOA_BASE + GPIOx_ODR_OFFSET, GPIOx_ODR_OD4_BIT);
    }
    counter++;
  }
}

void bit_clear(uint32_t address, uint8_t bit) {
  uint32_t mask = 1 << bit;
  volatile uint32_t *ptr = (uint32_t *) address;
  *ptr &= ~mask;
}

void bit_set(uint32_t address, uint8_t bit) {
  uint32_t mask = 1 << bit;
  volatile uint32_t *ptr = (uint32_t *) address;
  *ptr |= mask;
}

void bit_toggle(uint32_t address, uint8_t bit) {
  uint32_t mask = 1 << bit;
  volatile uint32_t *ptr = (uint32_t *) address;
  *ptr ^= mask;
}

Адреса брал из RM0360:

2.2.2 Memory map and register boundary addresses

AHB2 0x4800 0000 - 0x4800 03FF GPIOA
AHB1 0x4002 1000 - 0x4002 13FF RCC

7.4.6
Reset and clock control (RCC)
AHB peripheral clock enable register (RCC_AHBENR)
Address offset: 0x14
Bit 17: IOPAEN: I/O port A clock enable

8.4.1
GPIO port mode register (GPIOx_MODER)
Address offset:0x00
Bits 9:8 Port configuration bits
01: General purpose output mode

8.4.6
GPIO port output data register (GPIOx_ODR)
Address offset: 0x14
Bit 4: Port output databit

Насколько я понял из чтения документации:

  1. Нужно настроить регистр RCC_AHBENR и включить I/O port A.
  2. Нужно настроить регистр GPIOx_MODER и включить output mode для PA4.
  3. Для включения/выключения диода нужно менять бит GPIOx_ODR.

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

На CubeMX пример с HAL копипастил, он работает, диод моргает. Ниже приведу на всякий случай:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
	HAL_Delay(100);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Но я в нём ничего не понимаю, хотелось бы попроще.

vbr
()

Правильно ли я подключил МК?

 

Хочу поэкспериментировать с МК. Для этого собрал следующую конструкцию:

Плата Baite STM32F030F4

Модуль зарядки TP4056

Далее у меня есть плата Nucleo L073RZ мануал (стр. 16). Я от этой платы отрезал верхний кусок по линии разреза, как я понимаю, там находится программатор. У этого программатора я вытащил два джампера CN2 чтобы переключить его на работу с внешним МК.

Подключил я это всё следующим образом:

1 провод от модуля зарядки TP4056 с пометкой «OUT +» к плате Baite, пину «header 1 pin 5 VIN»

1 провод от модуля зарядки TP4056 с пометкой «OUT -» к плате Baite, пину «header 1 pin 6 GND»

4 провода от Nucleo L073RZ коннектор CN4 пины VDD_TARGET, SWCLK, GND, SWDIO к Baite пинам SWD header pins 3V3, SWCLK, GND, SWDIO

2 провода от Nucleo L073RZ пины TX RX к Baite пинам Serial header pins RX TX

Вообще вчера я подключал всё почти так же, только питание у модуля зарядки брал похоже не с тех разъёмов. В итоге на Baite шло нефильтрованное питание из USB (примерно 4.5В показывал мультиметр). В целом всё заработало, программу я смог залить, но периодически программатор показывал, что соединения с контролером нет.

Сегодня я питание подключил как выше написал, теперь там 4.2В, как я понимаю, более стабильное. Также запитал USB-порт отдельным блоком питания. Пока вроде не отваливается. Вообще допускаю, что я плохо что-то припаял, т.к. паять я не умею, модуль питания и контролер шли без гребёнок, я эту гребёнку к ним припаял и соединил всё на проводках с квадратными разъёмами.

Вопрос 1 - вообще всё правильно?

Вопрос 2 - для чего нужен пин VDD_TARGET? Я сначала подумал, что от него можно запитать контролер, но потом почитав понял, что он питание не даёт а наоборот проверяет.

Вопрос 3 - для чего я подключил TX/RX? Я сам не знаю. Как-то через ST Link можно получить к нему доступ?

Вопрос 4. Можно ли куда-то подключить пин с программатора NRST? Я так понимаю, это удобная штука для перезагрузки контролера, но куда его подключить я не нашёл. Или он не нужен?

vbr
()

Контроль своего домена

 

Предположим, мне не нравится, что гугл в любой момент может забанить мой username@gmail.com, на который завязана вся моя цифровая жизнь.

Ну как линуксоид я иду и покупаю домен. Настраиваю на этот домен почтовый ящик и вот уже я me@username.com, счастье.

Но есть одно «но». Чтобы купить домен, мне надо зарегистрироваться на каком-нибудь namecheap-е. И для регистрации мне нужна… Правильно, почта.

Если я потеряю доступ к своей исходной почте, любая проблема с аккаунтом и доступ к домену я теряю.

Что же делать?

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

Альтернативно: можно после покупки домена и настройки почтового сервера у регистратора сменить почту. Рекурсивненько получается. Но опять же это рецепт для проблем. Забыл домен оплатить вовремя, побежал его продлевать - а зайти не можешь и почта не ходит уже.

Я даже думал завести отдельную почту как раз для такой цели - регистрировать на неё самое важное. И желательно не в гугле. Но я не нашёл ни одного крупного почтового сервера, который бы обещал, что он никогда не удалит аккаунт. У всех есть оговорки, что если вы не заходите полгода, мы имеем право удалить аккаунт. Ну я каждого не изучал, только самых крупных, а мелкие и сами закрыться могут.

vbr
()

Постгрес в контейнере и ограничение по памяти?

 , ,

Имеется постгрес в контейнере в кубе. За несколько дней у него растёт потребление по памяти постепенно. Пока не дорастает до лимита, процесс-коннект не прибивает ООМ-ом и всё заново не происходит. Кажется, что это не совсем хорошо. Хочется навести порядок. Начинал с 60M, уже 300M ему выделил, он сегодня до 200 дорос, как чайный гриб, растёт и всё, при том, что он и на 60M работал - ему 200M явно не надо.

Причём судя по тому, что, скажем, он 3 дня работает нормально, это явно не какие-то там пики и тд, просто память утекает в какие-то кеши или хз куда.

В идеале хочется задать постгресу Xmx60m как жаве и он за пределы этих 60m не вылазил и сам рассчитал там размеры для своих кешей и прочего. А не ронял процессы по ООМ.

Как тут правильно поступить?

vbr
()

Как грамотно запустить контейнер, чтобы работал Ctrl+C

 , , ,

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

Первое, что пробовал это ENTRYPOINT ["sleep", "infinity"]. Не сработало. sleep игнорирует сигналы. Всякие вариации вроде bash -c "sleep infinity" или bash -c "exec sleep infinity" тоже не работают.

Лучшее, что придумал - ENTRYPOINT ["sh", "-c", "while sleep 1; do true; done"]. Но немного некрасиво - секунду всё равно ждать и крутится там туда-сюда, запускает sleep всё время. И кажись для SIGSTOP не работает, только для SIGINT.

Какой самый классный и короткой способ сделать так, чтобы и по сигналу (SIGINT и SIGSTOP) завершало выполнение, и чтобы в рамках sh работало, и выглядело не монструозно. Через всякие trap-ы и kill-ы и я смогу, но там строк на 10 будет в лучшем случае.

vbr
()

А вы пытаетесь соблюдать FHS в контейнерах?

 

Почему-то коробит, когда делают контейнеры с /data, /app и прочим бредом. Всегда делаю контейнеры с /home/build, /opt/app, /srv/data, /mnt/host и тд, пытаясь хоть как-то в FHS. Для меня создавать рандомный каталог в корне это какое-то кощунство. Вполне могу себе представить, что с таким подходом кто-нибудь смонтирует что-нибудь в /dev, типа среда разработки.

А вы как думаете? Есть в этом смысл?

vbr
()

Помогите улучшить хук usePromise

 

Пытаюсь подружить реакт с промисами. React Query и прочую муть не предлагать.

Пока родился такой вариант. Думаю, из сигнатур очевидно, как оно должно работать. Не нравится то, что reducer получился «не чистый». Вызывает abortController.abort(). Хотя и идемпотентный но кажется это всё равно не по феншую.

Как сделать нормально - я не придумал. Хотя думал много и это далеко не первая итерация. Буду благодарен помощи от гуру, если у кого будет хорошая идея.

import { DependencyList, useEffect, useReducer } from "react";

type PromiseFunction<T> = (signal: AbortSignal) => Promise<T>;

type Result<T> =
  | { status: "pending" }
  | { status: "fulfilled"; value: T }
  | { status: "rejected"; reason: unknown };

type State<T> =
  | { status: "uninitialized" }
  | { status: "pending"; id: number; abortController: AbortController }
  | { status: "fulfilled"; value: T }
  | { status: "rejected"; reason: unknown };

type Action<T> =
  | { type: "init"; id: number; abortController: AbortController }
  | { type: "resolve"; id: number; value: T }
  | { type: "reject"; id: number; reason: unknown }
  | { type: "clean" };

function reducer<T>(state: State<T>, action: Action<T>): State<T> {
  switch (action.type) {
    case "init":
      switch (state.status) {
        case "uninitialized":
          return {
            status: "pending",
            id: action.id,
            abortController: action.abortController,
          };
      }
      break;

    case "resolve":
      switch (state.status) {
        case "uninitialized":
          return state;
        case "pending":
          if (action.id < state.id) {
            return state;
          }
          if (action.id == state.id) {
            return { status: "fulfilled", value: action.value };
          }
          break;
      }
      break;

    case "reject":
      switch (state.status) {
        case "uninitialized":
          return state;
        case "pending":
          if (action.id < state.id) {
            return state;
          }
          if (action.id == state.id) {
            return { status: "rejected", reason: action.reason };
          }
          break;
      }
      break;

    case "clean":
      switch (state.status) {
        case "pending":
          state.abortController.abort();
          return { status: "uninitialized" };
        case "fulfilled":
        case "rejected":
          return { status: "uninitialized" };
      }
      break;
  }

  console.error("Unexpected state", state, action);
  return state;
}

function loggingReducer<S, A>(
  reducer: (state: S, action: A) => S,
): (state: S, action: A) => S {
  return (state, action) => {
    try {
      const nextState = reducer(state, action);
      console.log(state, action, nextState);
      return nextState;
    } catch (e) {
      console.log(state, action, e);
      throw e;
    }
  };
}

let nextId = 1;

export default function usePromise<T>(
  promiseFunction: PromiseFunction<T>,
  deps: DependencyList,
): Result<T> {
  const [state, dispatch] = useReducer(loggingReducer(reducer<T>), {
    status: "uninitialized",
  });

  useEffect(() => {
    const id = nextId++;
    const abortController = new AbortController();

    dispatch({ type: "init", id, abortController });

    promiseFunction(abortController.signal).then(
      (value) => dispatch({ type: "resolve", id, value }),
      (reason) => dispatch({ type: "reject", id, reason }),
    );

    return () => dispatch({ type: "clean" });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, deps);

  switch (state.status) {
    case "uninitialized":
    case "pending":
      return { status: "pending" };

    case "fulfilled":
      return { status: "fulfilled", value: state.value };

    case "rejected":
      return { status: "rejected", reason: state.reason };
  }
}

vbr
()

prometheus, whitelisting всего

 

Хочу начать освоение прометеуса с малого.

К примеру есть адрес someserver.com/metrics

Он выплёвывает кучу всего. Мне из всего этого нужно только одна метрика:

base_gc_time_total_seconds{name="G1 Old Generation"} 0.0
base_gc_time_total_seconds{name="G1 Young Generation"} 0.303

Причём вот этот label мне не нужен, я хочу его убрать. Чтобы в базе лежало только одно значение - сумма этих двух значений.

Как убирать лишние метрики я вроде понял:

    metric_relabel_configs:
      - source_labels: [ __name__ ]
        regex: base_gc_time_total_seconds
        action: keep

А вот как убрать лишние label-ы - я не понял. Можно использовать labeldrop, но кажется это не то, он не будет комбинировать получившиеся метрики, а получится какая-то смесь.

То, что можно сумму посчитать в запросе потом это понятно, я в принципе не хочу хранить эту метрику в двух экземплярах.

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

В общем по сути хочу включать метрики потихоньку добавляя нужные мне метрики и label-ы, а не всё скопом. Типа добавил base_gc_time_total_seconds, а все label-ы у него убрал. Потом разобрался - что мне нужна более тонкая статистика и добавил этот name конкретно к этой метрике.

vbr
()

Как проверить oom killer?

 ,

Завис сервер. Я рассчитывал, что он отвиснет, когда oom killer что-нибудь прибьёт, а он не отвисает до сих пор. Подожду до завтра, но явно ситуация не нормальная. Поэтому на соседнем сервере пытаюсь разобраться.

Сам я ничего не настраивал специально, свопа у системы нет. Система установлена из облачного образа debian.

Почему создал тему - в интернете на каждом сайте пишут, что оно контролируется через sysctl vm.oom-kill. Но у меня такого нет:

debian@worker-d-3:~$ /usr/sbin/sysctl vm.oom-kill
sysctl: cannot stat /proc/sys/vm/oom-kill: No such file or directory
debian@worker-d-3:~$ ls /proc/sys/vm
admin_reserve_kbytes         dirty_ratio                max_map_count              nr_hugepages              overcommit_ratio          user_reserve_kbytes
block_dump                   dirty_writeback_centisecs  memory_failure_early_kill  nr_hugepages_mempolicy    page-cluster              vfs_cache_pressure
compact_memory               dirtytime_expire_seconds   memory_failure_recovery    nr_overcommit_hugepages   page_lock_unfairness      watermark_boost_factor
compact_unevictable_allowed  drop_caches                min_free_kbytes            numa_stat                 panic_on_oom              watermark_scale_factor
compaction_proactiveness     extfrag_threshold          min_slab_ratio             numa_zonelist_order       percpu_pagelist_fraction  zone_reclaim_mode
dirty_background_bytes       hugetlb_shm_group          min_unmapped_ratio         oom_dump_tasks            stat_interval
dirty_background_ratio       laptop_mode                mmap_min_addr              oom_kill_allocating_task  stat_refresh
dirty_bytes                  legacy_va_layout           mmap_rnd_bits              overcommit_kbytes         swappiness
dirty_expire_centisecs       lowmem_reserve_ratio       mmap_rnd_compat_bits       overcommit_memory         unprivileged_userfaultfd

Видимо гайды устарели. Как правильно проверить? Ядро 5.10.0-20-amd64

В /usr/lib/systemd/ бинарника systemd-oomd тоже нет и сервиса соответствующего тоже нет, если что.

vbr
()

Файловая система для SD-карт

 , , , ,

Есть смысл смотреть на что-то вроде F2FS или сейчас нормальные карты от SSD не отличаются и сами балансируют записи по блокам, то бишь стандартный Ext4 будет предпочтительней?

Помимо прочего крайне необходимо, чтобы не было порчи ФС при выключении питания. Данные хранятся в sqlite, поэтому важно, чтобы sqlite оставалась в работоспособном состоянии.

vbr
()

raspberry, buildroot, wayland

 , ,

Хочу сделать на raspberry киоск с веб-интерфейсом (чтобы после загрузки открывался браузер на весь экран с HTML с диска).

Как я понял, свой линукс надо собирать через buildroot, вместо electron надо использовать wpewebkit и сейчас графика работает через wayland.

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

Минимальный образ buildroot-ом с помощью make raspberrypi4_defconfig я собрал, он грузится, консоль есть, залогиниться можно. buildroot 2022.02.8

Далее долго пытался найти минимальный подбор опций, чтобы получилось выбрать wpewebkit. Вышло примерно следующее:

Toolchain
 Enable WCHAR support
Target packages
 Graphic libraries and applications (graphic/text)
  mesa3d
   Gallium vc4 driver
   OpenGL ES
 Libraries
  Graphics
   wpewebkit
 Graphic libraries and applications (graphic/text)
  cog
   Wayland backend
Filesystem images
 ext2/3/4 root filesystem
  exact size: 180M

cog это, как я понимаю, браузер на этом wpewebkit, т.е. видимо то, что и должно показать мою HTML-ку и то, что я должен буду настроить на автозапуск.

В итоге cog этот не запускается. Пишу cog (от рута), он начинает в цикле писать (сокращаю, т.к. перепечатываю)

error: XDG_RUNTIME_DIR not set in the environment.
WARNING Your application does not implement g_application_activate() and has no handlers connected to the activate signal. It should do one of these.
libEGL warning: MESA-LOADER: failed to open swrast: File not found (search paths /usr/lib/dri, suffix _dri)

EGLDisplay initialization failed: EGL_NOT_INITIALIZED

Cog Core WARNING THe rendered process crashed.

XDG_RUNTIME_DIR ставил, эта ошибка ушла, толку не было.

Что за libEGL warning я не понял. В /usr/lib/dri файла swrast_dri.so нет. Есть файл vc4_dri.so. Как я предполагаю, swrast это софтовый растеризатор, а vc4 это хардварный. Как этому libEGL сказать, чтобы он использовал vc4, я пока не понял, гугл не очень помогает.

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

Пробовал запускать cog --platform=wl, пишет preferred modulewlnot supported, cannot create platformm: could not find an usable platform module. could not load the impl library. Is there any backend installed? File not foudn.

Может я вообще не в том направлении двигаюсь? raspi в целом это больше прототип, потом надо будет это на i.mx8 делать, поэтому хочу через buildroot сделать.

Также пробовал включать v3d драйвер, не помогло.

vbr
()

RSS подписка на новые темы