Является ли исполняемый файл переносимым между разными хостами Nixos, которые ссылаются на разные коммиты nixpkg?

Проблема в том, что нужно чтение с тайм-аутом . Если firehoseничего не отправляет, ваш цикл блокируется на неопределенное время , и когда он это делает, он не может отправить последнюю полученную строку. Bash имеет аргумент -t для чтения по времени -. Если у zsh readесть это, то это то, что нужно использовать.

Алгоритм заключается в том, чтобы продолжать чтение строк с тайм-аутом, который всегда повторно -вычисляется (укорачивается все больше и больше )до истечения одной секунды (или любого другого )интервала. Когда этот интервал наступит, тогда, если одна или несколько строк были прочитаны, отправьте последнюю. В противном случае ничего не отправляйте и начинайте читать строки для следующего интервала.

Вы можете реализовать «мгновенный проход» для самой первой полученной строки или для первой строки, полученной по прошествии периода времени, превышающего интервал. Например, если интервал равен 1 секунде, и ничего не пришло из firehoseв течение 1,5 с момента последнего вывода строки, то эту строку можно пройти, и механизм может сбросить, чтобы начать новый интервал в одну секунду в этой точке..

Это доказательство -реализации концепции -в TXR Lisp работает для меня, подтверждая базовый алгоритм:

(defvarl %interval% 1000000) ;; us

(defun epoch-usec ()
  (tree-bind (sec. usec) (time-usec)
    (+ (* 1000000 sec) usec)))

(let ((now (epoch-usec))
      (*stdin* (open-fileno (fileno *stdin*) "rl")) ;; line buffered
      remaining-time next-time line done)
  (while (not done)
    (set next-time (+ now %interval%))
    (set remaining-time (- next-time now))
    (while (poll (list (cons *stdin* poll-in))
                 (trunc remaining-time 1000))
      ;; got a line or EOF poll: no timeout
      (iflet ((nline (get-line)))
        (set line nline)              ;; got line
        (progn (flip done) (return))) ;; EOF poll
      (set now (epoch-usec))
      (when (minusp (set remaining-time (- next-time now)))
        (return)))
    ;; timeout, past deadline or exit: flush line, if any:
    (when line
      (put-line line)
      (set line nil))))

Настроен небуферизованный поток, так как pollиспользуется для считывания по времени -вывода, а pollне видит буферов потока. Идея состоит в том, что мы не хотим опрашивать ввод, пока в потоке есть непрочитанные буферизованные данные. Это придирка. При тестировании я не увидел качественной разницы в поведении между этим и просто использованием буферизованного исходного потока *stdin*. Если мы тратим время на опрос, когда в потоке есть буферизованные данные, а в дескрипторе файла их нет, мы гарантированно не будем ждать дольше, чем наш интервал времени, и меньше, если новые данные поступят раньше.

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

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

Эти тестовые примеры выполняются без заметной задержки:

$ echo foo | txr throttle.txr
foo
$ (echo foo; echo bar) | txr throttle.tl 
bar
$ (echo foo; echo bar; echo xyzzy) | txr throttle.tl 
xyzzy

Тогда:

$ (echo foo; sleep 2; echo bar; sleep 2; echo xyzzy) | txr throttle.tl 
foo
bar
xyzzy

Я тестировал find / | txr throttle.tlи тому подобное.

0
24.08.2019, 12:14
1 ответ

Пакеты, созданные Nix, обычно используют DT_RUNPATHзапись в файлах ELF для поиска общих библиотек. Вы можете использовать, например, nix run -f. patchelf -c patchelf --print-rpath appдля просмотра записей. В вашем случае он вернет что-то вроде этого:

/nix/store/7gx4kiv5m0i7d7qkixq2cwzbr10lvxwc-glibc-2.27/lib:/nix/store/sf3jq8d81gx6fmxsi0mhagpgsgpnxf6m-postgresql-9.6.12-lib/lib

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

Если вы знаете коммит nixpkgs, который вы использовали для сборки программы, вы можете запустить nix-build -f https://github.com/NixOS/nixpkgs/archive/${commit}.tar.gz -A postgresql.libна втором компьютере, чтобы добавить библиотеку в хранилище. Но имейте в виду, что если вы не добавите его в корень GC, он может быть очищен сборщиком мусора.

Если вы построили свою программу как выражение Nix, довольно легко экспортировать все замыкание и импортировать его на другой компьютер.

2
28.01.2020, 02:40

Теги

Похожие вопросы