Кластер Node.js; беспорядочный вывод консоли ТОЛЬКО при использовании цвета

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

Моя проблема: я получаю путаницу, консольный вывод состояния гонки-y ТОЛЬКО ПРИ ИСПОЛЬЗОВАНИИ ЦВЕТОВ.

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

let chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let getMyUniqueString = () => {
  return chars[Math.floor(Math.random() * chars.length)].repeat(100);
};

Я запускаю кучу узлов, которые используют эту функцию для определения своих уникальных строк, и вижу что-то вроде следующего:

Вывод в консоль без путаницы

Разве это не красиво! Независимо от того, как долго и как яростно выводятся все эти узлы, этот вывод консоли никогда не будет беспорядочным.

Теперь я пробую использовать уникальные строки, содержащие совсем немного цвета:

let chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let getMyUniqueString = () => {
  let redEscSeq = '\x1b[41m';
  let clearEscSeq = '\x1b[0m';
  let aRedBoxOfText = redEscSeq + '  ' + clearEscSeq;
  let repeatedChars = chars[Math.floor(Math.random() * chars.length)].repeat(100);
  return aRedBoxOfText + repeatedChars;
};

И посмотрите, как печально выглядят некоторые мои результаты!

введите здесь описание изображения

ЕДИНСТВЕННЫЙ способ отправки данных на терминал через все узлы - это функция console.log.

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

Спасибо за любую помощь!

(Просто для справки, следующее изображение - это тот вид несвязанного вывода, который я ожидал бы постоянно видеть в цветном корпусе; это просто красный прямоугольник (два пробела с красным цветом фона) перед каждой строкой :)

введите здесь описание изображения

РЕДАКТИРОВАТЬ: Хотя эта проблема существует в собственной консоли Windows «cmd.exe», в консоли PowerShell и в ConEmu (красивый сторонний терминал Windows, показанный на снимках экрана), она НЕ существует в терминале Cygwin! В Cygwin никогда не бывает путаницы, даже с тоннами цветов и асинхронным выводом. Могу ли я что-нибудь сделать, чтобы поощрить такое поведение Cygwin на других консолях?


person Gershy    schedule 03.10.2018    source источник
comment
Возможно ли, что это проблема Windows / unix Unicode или проблема с окончанием строки, такая как CRLF vs LF?   -  person Andrei    schedule 23.10.2018
comment
Также согласно wiki окна наивно не поддерживают раскраску ANSI, возможно, вам нужно убедиться, что в этой командной строке используется Windows 10, а не устаревшая   -  person Andrei    schedule 23.10.2018


Ответы (1)


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

Хотя сам Windows API фактически поддерживает печать разноцветной строки за один вызов API, как показано здесь: https://docs.microsoft.com/en-us/windows/console/writeconsoleoutput, где каждый символ содержит информацию о своем цвете. Но он также не поддерживает escape-коды ANSI. И это не то, что на самом деле используется javascript.

Движок Nodejs использует библиотеку под названием libuv для записи строк в терминал, которая является кроссплатформенной и внутренне переводит управляющие коды ANSI, чтобы поступать правильно. Но если вы внимательно посмотрите на для обработки управляющих кодов ANSI, вы увидите, что он выполняет полную очистку буфера после каждого escape-кода, что означает, что в какой-то момент он должен превратиться в несколько вызовов API Windows для печати одной строки текста.

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

Итак, ответ здесь - решения нет. Или вы соглашаетесь использовать cygwin в качестве решения.

person barteks2x    schedule 24.10.2018
comment
Я все еще немного смущен тем, как cygwin удается правильно работать - определяет ли libuv и адаптируется ли к типу терминала, с которым связан console.log? Избегает ли libuv выполнения этой очистки буфера, когда обнаруживает, что консоль используется cygwin? Дайте мне знать как можно скорее, так как срок действия награды истекает, и я хочу иметь возможность ее назначить! - person Gershy; 24.10.2018
comment
Вы запускали версию nodejs для cygwin на cygwin? Если это так, очень вероятно, что в libuv использовался специфичный для unix код, в котором этой проблемы нет. Если это подтвердится, я обновлю свой ответ, включив его и, возможно, добавлю больше деталей. - person barteks2x; 24.10.2018
comment
Больше нельзя редактировать исходный комментарий, но даже если вы действительно использовали обычную версию node на cygwin, также возможно, что он загрузил unix-версию libuv оттуда, скомпилированную под cygwin. Это также объяснило бы проблему. Также может быть возможно заставить его работать правильно, используя WSL (подсистема Windows для Linux). - person barteks2x; 24.10.2018
comment
Вы должны иметь возможность подтвердить эту гипотезу, запустив cygwin bash из обычного терминала Windows и запустив оттуда узел. Если проблема не возникает, скорее всего, она загружается с использованием специфичного для unix кода в libuv. - person barteks2x; 24.10.2018