LINUX.ORG.RU

Сообщения 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
()

Почему не работает suid бит

 

Хочу взломать свой компьютер через докер.

Запустил в конейнере линукс, подмонтировал туда локальную папку. В неё предварительно скопировал sh. Сделал chmod u+s sh из докера. Вышел из докера - suid бит остался. Запускаю этот sh ожидая, что suid бит его запустит под рутом - но не получается.

vbr@13049:~/test$ ls -la
total 132
drwxr-xr-x 2 vbr vbr   4096 Dec  4 05:51 .
drwxr-xr-x 8 vbr vbr   4096 Dec  4 05:47 ..
-rwsr-xr-x 1 root      root      125560 Dec  4 05:47 sh
vbr@13049:~/test$ stat sh
  File: sh
  Size: 125560    	Blocks: 248        IO Block: 4096   regular file
Device: 801h/2049d	Inode: 3951222     Links: 1
Access: (4755/-rwsr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2022-12-04 05:52:33.620839091 +0600
Modify: 2022-12-04 05:47:48.758333113 +0600
Change: 2022-12-04 05:52:24.856885055 +0600
 Birth: 2022-12-04 05:47:48.758333113 +0600
vbr@13049:~/test$ ./sh 
$ id
uid=1001(vbr) gid=1001(vbr) groups=1001(vbr),997(docker)
$ ls /root
ls: cannot open directory '/root': Permission denied

Никаких маунтов с nosuid нет.

vbr
()

self hosted github runner в публичном репозитории

 ,

Имеется организация в github на бесплатном тарифе.

Имеется несколько закрытых репозиториев.

Хочется иметь reusable workflow, который можно вызывать из этих закрытых репозиториев. Хранить его нужно в публичном репозитории, т.к. на бесплатном тарифе нельзя вызывать reusable workflow из закрытых репозиториев.

К этой организации прикреплены self hosted runners. Они должны использоваться для этого workflow.

В документации написано:

We recommend that you only use self-hosted runners with private repositories. This is because forks of your public repository can potentially run dangerous code on your self-hosted runner machine by creating a pull request that executes the code in a workflow.

В самом публичном репозитории с reusable workflows ничего кроме них самих и какой-нибудь документации ничего не будет.

Хочется понять, как правильно и безопасно это всё организовать.

vbr
()

.gitignore: всё в secrets/ кроме *.example.*

 

Есть каталог some/path/secrets/ в нём есть два файла: name.env и name.example.env. Нужно заигнорить первый и разигнорить второй. Таких каталогов и файлов много, нужно универсальное правило.

Логичный вариант (в корне) не сработал

secrets/
!secrets/*.example.*

он всё игнорит в итоге. Пробовал некоторые вариации, не получилось.

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

vbr
()

Как вычитать http запрос?

 

Хочу вычитать входящий запрос по протоколу HTTP 1.0 или 1.1 и послать ответ, в котором будет текст запроса.

Я так понимаю, простой алгоритм вида «читать, пока клиент не закрыл соединение» не сработает, т.к. современные клиенты пытаются в http keepalive и соединение надо закрывать самому со стороны сервера. Но чтобы закрыть соединение, мне нужно вычитать весь запрос.

Выходит, придётся парсить запрос.

Я так понимаю, есть три алгоритма:

transfer-encoding не указан и content-length не указан. Тогда читаем до закрытия соединения.

content-length указан. Тогда читаем указанное число байтов (ну или до закрытия соединения, что будет странно).

указан transfer-encoding и в нём присутствует chunked. Тогда читаем чанки, пока не придёт чанк нулевой длины, что сигнализирует конец запроса.

Пока не понял, что делать, если указан и chunked и content-length, но я прочитаю.

Можно ли считать, что этого хватит для любых разумных и неразумных (но в рамках протокола) запросов?

vbr
()

Альтернативы keycloak

 

Ищу легковесную альтернативу Keycloak.

Хотелки:

  • Всякие oauth штуки. Тут нужна достаточно продвинутая поддержка - маппинг групп, audience.
  • Своя база юзеров с паролями.
  • Страница логина. Регистрация не нужна.
  • Функционал сброса пароля путём отправки ссылки на почту через SMTP-сервер с авторизацией.
  • Sqlite база или что-то подобное.
  • Админка для просмотра, добавления и редактирования пользователей.
  • Настройки realm-а и прочих oauth штук через конфиги, а не как в keycloak в базе/UI. Чтобы можно было конфиг поменять и запустить с изменённым конфигом, а не тыкаться там по менюшкам.

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

В кейклоке не устраивает:

  • Долгий старт, несколько минут. Они предлагают собирать свой образ. Это неудобно.
  • Жрёт под половину гигабайта на пустой базе.
  • Конфиг в базе хранится. Нет удобного способа делать что-то, похожее на gitops. На terraform можно сделать, но это бред какой-то.
  • Работает на взрослой базе вроде постгреса. У меня нагрузка смешная, мне это не надо, гемор по поддержке полноценной базы не хочу.
vbr
()

Решето

 ,

Sudo 1.8.0 through 1.9.12, with the crypt() password backend, contains a plugins/sudoers/auth/passwd.c array-out-of-bounds error that can result in a heap-based buffer over-read. This can be triggered by arbitrary local users with access to Sudo by entering a password of seven characters or fewer. The impact could vary depending on the compiler and processor architecture.

vbr
()

Без чего вы не обходитесь на андроиде?

 

По случаю санкций решил пересесть с айфона на андроид. Зонд это хорошо, но когда у тебя отбирают двагис, это плохо. Купил пиксель 7, вроде говорят, что у гугла самые приятные ощущения.

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

Пока на аосп/ф-дроид переезжать не планирую, но держу этот вариант в уме на всякий случай.

Собственно что вы бы поставили себе на телефон из неочевидных приложений? Может лаунчер какой маст хэв или файловый менеджер. И почему. Что не хватает в стандартном?

vbr
()

ZeroSSL существует

 , ,

У letsencrypt есть неприятная особенность. У него стоит ограничение на 5 сертификатов в неделю для определенного имени. То бишь можно выпустить ровно 5 сертификатов для www.linux.org.ru, к примеру. Если этот лимит превышен, можно запросить сертификат для двух доменов вроде www.linux.org.ru, www1.linux.org.ru и он его успешно выпустит ещё 5 раз и тд.

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

Тут внезапно узнал про сабж. Работает по протоколу ACME, то бишь вообще ничего менять не нужно кроме URL сервера. И вроде как у него вообще нет никаких ограничений на число сертификатов и тд. Конечно бесплатен.

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

vbr
()

Запускать докер удаленно с пробросом портов

 ,

Я использую сервер, на котором запущен докер. Локально у меня установлен только клиент-бинарник. Соединение настроено через docker context поверх ssh.

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

Нет ли тут какого-то более удобного решения? Также должно работать с docker-compose. Теоретически я это вижу, как некоторый демон, который запускается локально, а также мониторит запущенные докер-контейнеры на удаленном хосте. И при появлении новых контейнеров с выставленными портами он будет автоматически пробрасывать эти порты на локальный компьютер.

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

$ s=someserver.com
$ docker run -d --rm --name nginx -p 127.0.0.1:8080:80 nginx
$ ssh $s curl -i --head -sS http://127.0.0.1:8080/
HTTP/1.1 200 OK
$ curl -i --head -sS http://127.0.0.1:8080/
curl: (7) Failed to connect to 127.0.0.1 port 8080 after 10 ms: Connection refused
$ ssh -L 127.0.0.1:8080:127.0.0.1:8080 -N $s
$ curl -i --head -sS http://127.0.0.1:8080/
HTTP/1.1 200 OK

Вот чтобы ssh -L не нужно было запускать, мне хочется.

vbr
()

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