Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Вывод в терминале строк с меняющимися данными в одну строку.  (Прочитано 6116 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн starky

  • Автор темы
  • Новичок
  • *
  • Сообщений: 34
    • Просмотр профиля
Наверное, это простая задача, но я с форматированием текста мало знаком, уже замучал поиск. Решил спросить у сообщества.
Есть программа 
./metrics_monitor, которая выводит в терминал поток строк такого вида
RENDER usage: 3.03, VIDEO usage: 0.00, VIDEO_E usage: 0.00 GT Freq: 533.00
RENDER usage: 1.01, VIDEO usage: 0.00, VIDEO_E usage: 0.00 GT Freq: 350.00
RENDER usage: 0.00, VIDEO usage: 0.00, VIDEO_E usage: 0.00 GT Freq: 350.00
RENDER usage: 0.00, VIDEO usage: 0.00, VIDEO_E usage: 0.00 GT Freq: 350.00
RENDER usage: 6.12, VIDEO usage: 0.00, VIDEO_E usage: 0.00 GT Freq: 967.00
RENDER usage: 55.79, VIDEO usage: 35.79, VIDEO_E usage: 0.00 GT Freq: 1000.00
RENDER usage: 71.43, VIDEO usage: 41.84, VIDEO_E usage: 0.00 GT Freq: 1000.00
RENDER usage: 64.58, VIDEO usage: 34.38, VIDEO_E usage: 0.00 GT Freq: 1000.00
RENDER usage: 62.64, VIDEO usage: 42.86, VIDEO_E usage: 0.00 GT Freq: 1000.00
RENDER usage: 65.98, VIDEO usage: 39.18, VIDEO_E usage: 0.00 GT Freq: 1000.00
RENDER usage: 68.37, VIDEO usage: 44.90, VIDEO_E usage: 0.00 GT Freq: 1000.00

Строки однотипные, но данные меняются. Однако неудобно следить когда они бегут и заполняют весь терминал. Как и чем отформатировать этот вывод, (не меняя программы, ибо проприетарная и похоже бинарник) чтобы каждая следующая строка писалась на место предыдущей, то есть замещала её на экране терминала (или предыдущая бы стиралась а новая записывалась на её место) Если учесть что некоторые разняться на несколько символов, еще и пробелов дописать в хвост тем строкам что короче, чтобы стирали собой более длинные.

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

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
Попробуй так:
Код: (bash) [Выделить]
./metrics_monitor | while read l; do echo -ne "\r${l}"; done
« Последнее редактирование: 26 Декабря 2016, 14:19:13 от renzrv »

Оффлайн starky

  • Автор темы
  • Новичок
  • *
  • Сообщений: 34
    • Просмотр профиля
./metrics_monitor | tail -f

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

Попутно нашел код проги на C. Не знаю, может в ней проще исправить что-то, и пересобрать? Она использует модуль libcttmetrics.so , который пришел уже скомпиленный, потому что там секреты Интел  :) Но саму прога симеет такой код

\* ****************************************************************************** */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include "cttmetrics.h"

volatile sig_atomic_t run = 1;

void signal_handler(int signo)
{
    if (SIGINT == signo)
    {
        run = 0;
    }
}

int main(int argc, char *argv[])
{
    cttStatus status = CTT_ERR_NONE;
    cttMetric metrics_ids[] = {CTT_USAGE_RENDER, CTT_USAGE_VIDEO, CTT_USAGE_VIDEO_ENHANCEMENT, CTT_AVG_GT_FREQ, CTT_USAGE_VIDEO2};
    unsigned int metric_cnt = sizeof(metrics_ids)/sizeof(metrics_ids[0]);

    unsigned int num_samples = 100;
    unsigned int period_ms = 500;

    if (1 < argc && NULL != argv[1])
    {
        num_samples = atoi(argv[1]);
    }

    if (2 < argc && NULL != argv[2])
    {
        period_ms = atoi(argv[2]);
    }

    signal(SIGINT, signal_handler);

    status = CTTMetrics_Init();
    if (CTT_ERR_NONE != status)
    {
        fprintf(stderr, "ERROR: Failed to initialize metrics monitor, error code %d\n", (int)status);
        return 1;
    }

    unsigned int metric_all_cnt = 0;
    status = CTTMetrics_GetMetricCount(&metric_all_cnt);
    if (CTT_ERR_NONE != status)
    {
        fprintf(stderr, "ERROR: Failed to get number of metrics available, error code %d\n", (int)status);
        return 1;
    }

    cttMetric metric_all_ids[CTT_MAX_METRIC_COUNT] = {CTT_WRONG_METRIC_ID};
    status = CTTMetrics_GetMetricInfo(metric_all_cnt, metric_all_ids);
    if (CTT_ERR_NONE != status)
    {
        fprintf(stderr, "ERROR: Failed to get metrics info, error code %d\n", (int)status);
        return 1;
    }

    unsigned int i;
    bool isVideo2 = false;
    for (i = 0; i < metric_all_cnt; ++i)
    {
        if (CTT_USAGE_VIDEO2 == metric_all_ids[i])
          isVideo2 = true;
    }

    if (false == isVideo2)
        metric_cnt = metric_cnt - 1; // exclude video2 usage metric

    bool isFreq = false;
    for (i = 0; i < metric_all_cnt; ++i)
    {
        if (CTT_AVG_GT_FREQ == metric_all_ids[i])
          isFreq = true;
    }

    if (false == isFreq)
        metric_cnt = metric_cnt - 1; // exclude average frequency metric

    status = CTTMetrics_Subscribe(metric_cnt, metrics_ids);
    if (CTT_ERR_NONE != status)
    {
        fprintf(stderr, "ERROR: Failed to subscribe for metrics, error code %d\n", (int)status);
        return 1;
    }

    status = CTTMetrics_SetSampleCount(num_samples);
    if (CTT_ERR_NONE != status)
    {
        fprintf(stderr, "ERROR: Failed to set number of samples, error code %d\n", (int)status);
        return 1;
    }

    status = CTTMetrics_SetSamplePeriod(period_ms);
    if (CTT_ERR_NONE != status)
    {
        fprintf(stderr, "ERROR: Failed to set measure interval, error code %d\n", (int)status);
        return 1;
    }

    float metric_values[metric_cnt];
    memset(metric_values, 0, (size_t)metric_cnt * sizeof(float));

    while(run)
    {
        status = CTTMetrics_GetValue(metric_cnt, metric_values);
        if (CTT_ERR_NONE != status)
        {
            fprintf(stderr, "ERROR: Failed to get metrics, error code %d\n", status);
            return 1;
        }
        printf("RENDER usage: %3.2f,\tVIDEO usage: %3.2f,\tVIDEO_E usage: %3.2f", metric_values[0], metric_values[1], metric_values[2]);

        if (true == isVideo2)
            printf("\tVIDEO2 usage: %3.2f", metric_values[4]);

        if (true == isFreq)
            printf("\tGT Freq: %4.2f", metric_values[3]);

        printf("\n");
    }

    CTTMetrics_Close();

    return 0;
}

А собирается такой командой
gcc cttmetrics_sample.cpp -m64 -I../include -L../_bin -lcttmetrics -lstdc++ -o metrics_monitor

Я в C "нибельмесы". И меняться поздно. Общее представление, когда-то на Forth системным программированием занимался, как любитель. А еще на ардуино копипастил, с небольшими правками. Отсюда некоторые навыки, но не более.

Надеюсь, эта задачка решается средствами  bash, все же.

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля

Оффлайн starky

  • Автор темы
  • Новичок
  • *
  • Сообщений: 34
    • Просмотр профиля
./metrics_monitor > file & tail -f file

Тоже не вышло. Через sudo писал что нет file. Вошел под рутом, при каждом запуске пишет одно число и останавливается.

[1] 3346
^C
[root@localhost sample]# ./run.sh > file & tail -f file
[2] 3354
^C
[root@localhost sample]# ./run.sh > file & tail -f file
[3] 3361
^C
[root@localhost sample]# ./run.sh > file & tail -f file
[4] 3367
^C

run.sh - это скрипт с этой программой, в котором еще переменная окружения устанавливается. Содержимое

export LD_LIBRARY_PATH=$PWD/../_bin:$LD_LIBRARY_PATH

./metrics_monitor

Забыл сказать, может это важно.
Если решение найдется, я его в этот скрипт прямо впишу. Внутрь. А кстати, надо сейчас вписать, вдруг измениться.

Пользователь добавил сообщение 26 Декабря 2016, 14:37:54:
Да, изменилось. Сначала задумался, потом выдал порцию из десятки строк, потом опять задумался, и стал выдавать время от времени по одной, или по пять строк сразу, и последняя обрезана. В общем не то, совсем. Через файл, по идее должна работать. Может как-то вырезать из вывода "перевод строки"? Ведь в команде top если экран не меняется, то данные меняются в своих строчках, а не бегут все время снизу вверх. Причем это для каждой строки сделано на своем месте. Должен быть способ.
« Последнее редактирование: 26 Декабря 2016, 14:37:54 от starky »

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
Пост обновил(upd) же давно. Смотреть не пробовал?

Оффлайн starky

  • Автор темы
  • Новичок
  • *
  • Сообщений: 34
    • Просмотр профиля
 Я пытаюсь выполнять внутри скрипта и снаружи.
Вот это     ./metrics_monitor | while read l; do echo -ne "\r${l}"; done
Сначала курсор мигал, в течении минуты получил вывод одной строки, вижу что значение меняется. Надо запустить рендер чтобы все значения забегали. Сейчас.

Пользователь добавил сообщение 26 Декабря 2016, 14:55:13:
В общем, оно выводится в одну строку, что запущенное внутри скрипта, что снаружи, то есть export не мешает. Но данные в этой строке обновляются раз в 15 -20 сек, а выдает ./metrics_monitor где-то 2 строки с данными в секунду.

Пользователь добавил сообщение 26 Декабря 2016, 14:56:06:
То есть почти получилось, но куда-то часть вывода пропадает, причем большая.
« Последнее редактирование: 26 Декабря 2016, 14:59:59 от starky »

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
Цитировать
мигал, в течении минуты
Это твоя программа задерку делает, но не цикл.

Цитировать
но куда-то часть вывода пропадает
Значит эта часть вероятно идет через STDERR, пробуй так:
Код: (bash) [Выделить]
./metrics_monitor 2>&1 | while read l; do echo -ne "\r${l}"; done
« Последнее редактирование: 26 Декабря 2016, 15:06:55 от renzrv »

Оффлайн starky

  • Автор темы
  • Новичок
  • *
  • Сообщений: 34
    • Просмотр профиля
./metrics_monitor 2>&1 | while read l; do echo -ne "\r${l}"; done

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

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
Цикл никаких задержек не добавляет, это может быть из-за перегрузки или слабого процессора, смотри top.
Для теста сравни с:
while : ; do date '+%s.%N' ; sleep 0.1 ; done | while read l ; do echo -ne "\r${l}"; done
« Последнее редактирование: 26 Декабря 2016, 15:16:40 от renzrv »

Оффлайн starky

  • Автор темы
  • Новичок
  • *
  • Сообщений: 34
    • Просмотр профиля
Задержка не зависит от нагрузки на процессор. В простое загрузка проца около процента, при этом скорость выдачи данный "метриксом" не меняется, а задержка плавает, я ошибся, мерял с секундомером, интервалы плавают, значит зависят от содержимого.
Заодно проверил алгоритм рендеринга. При любой нагрузке извне драйвер перекидывает мощности на систему, то есть если я двигаю окно, процессор разгружается. Основную работу делают графический ускоритель, рендер идет на intel quick sync. Это и видно данным в строке - видео ядро загружено процентов на 70.
Думаю, что парсинг происходит не так как ожидается.
Главное что в простое все равно задержка, а этот проц 4K видео без труда тянет. но при 1 - 1.5 % загрузки причина должна быть в другом.


Пользователь добавил сообщение 26 Декабря 2016, 15:27:39:
while : ; do date '+%s.%N' ; sleep 0.1 ; done | while read l ; do echo -ne "\r${l}"; done

Это дает

Цитировать
bash: syntax error near unexpected token `do'

Пользователь добавил сообщение 26 Декабря 2016, 15:29:59:
У меня от таких выражений ум за разум заходит. Я начинаю понимать, что понимаю еще меньше, чем раньше. Хотя и раньше не много понимал.
Типа как "тупой и еще тупее". Только я думал, что тупее уже быть не могу, как мне попадается нечто вроде этого

while : ; do date '+%s.%N' ; sleep 0.1 ; done | while read l ; do echo -ne "\r${l}"; done
 :)

Пользователь добавил сообщение 26 Декабря 2016, 15:36:42:
while : ; do date '+%s.%N' ; sleep 0.1 ; done | while read l ; do echo -ne "\r${l}"; done


АБ этот цикл надо сам по себе запустить, без метрикса. Работает. Нагрузка на проц - ну не видно её. Кстати топ показывает, что у меня уже несколько процессов метрикс монитора идут. Но каждый всего 1 процент проца берет. Надо их убить все рано.
« Последнее редактирование: 26 Декабря 2016, 15:37:23 от starky »

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
Цитировать
В простое загрузка проца около процента
Смотреть надо макс. загрузку при работе программы с циклом.

Цитировать
Это дает
bash: syntax error near unexpected token `do'
Не дает, ошибок нет. Это ты что-то изменил.

Цитировать
все равно задержка
А как ты отличаешь задержку вывода от вывода дублирующихся строк?
« Последнее редактирование: 26 Декабря 2016, 15:45:21 от renzrv »

Оффлайн starky

  • Автор темы
  • Новичок
  • *
  • Сообщений: 34
    • Просмотр профиля
Там все время меняется частота видеоядра в простое, Примерно раз в 5 -10 секунд. (Последнее значение в строке) И RENDER usage: в пределал процента - двух периодически, несколько раз за десять секунд -  там второй монитор подключен. Я знаю что эти значения меняются быстрее, чем это происходит в "финальной строке". Ну а когда кодирование файла запуская, то хоть одно значение в секунду, но меняется. Нагрузка на видео - ядро величина плавающая. Так все и видно.

Сейчас запущен монитор, top показывает нагрузку 0.7 от мониторинга с парсером. Это в холостую.

А если в коде на С где-нибудь в финальном выводе просто убрать "перевод строки"?

Пользователь добавил сообщение 26 Декабря 2016, 15:54:00:
bash: syntax error near unexpected token `do

Да, я потом понял, что надо отдельно запускать. Но эта строка "не ощутима" для проца сама по себе. Дело не нагрузке на систему, "парсер" просто пропускает часть вывода, я думаю, по какой-то причине. Но я не понимаю что он делает. Хоть прогресс есть, теперь строка только одна. :)
« Последнее редактирование: 26 Декабря 2016, 15:54:00 от starky »

Оффлайн SergeyIT

  • Зануда.
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 5738
  • Все по палатам!
    • Просмотр профиля
А если в коде на С где-нибудь в финальном выводе просто убрать "перевод строки"?
Можно, но надо тогда команду дать перемещения курсора в начало строки... а есть ли такая в этом режиме, не знаю.
Вот если перевести терминал в другой режим (VT52) то можно сделать все.
Извините, я все еще учусь

Оффлайн ReNzRv

  • Старожил
  • *
  • Сообщений: 2648
    • Просмотр профиля
Все лишние процессы metrics_monitor нужно убить, из-за этого и могла идти задержка.

Цитировать
А если в коде на С где-нибудь в финальном выводе просто убрать "перевод строки"?
В конце:
Код: (C++) [Выделить]
        printf("\n");
    }

    CTTMetrics_Close();

    return 0;
}
поробуй заменить
Код: (C++) [Выделить]
printf("\n");на
Код: (C++) [Выделить]
printf("\r");
« Последнее редактирование: 26 Декабря 2016, 16:00:01 от renzrv »

 

Страница сгенерирована за 0.022 секунд. Запросов: 21.