Помогите идеей. Нужен счетчик потока данных. bash

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

evgeny2k
Сообщения: 26
ОС: mandriva 2008 spring

Помогите идеей. Нужен счетчик потока данных. bash

Сообщение evgeny2k »

Всем привет.
Не могу придумать, как считать количество прокачанных через что-то данных. Для примера:
cat /dev/sda | bzip2 -9 > disk.img льёт, ужимая на лету, образ в файл. Хотелось бы получить что-то,
что можно было бы вставить в подобную команду и получать значение объема данных, прокачаного
на текущий момент. Т.е. иметь примерно следующую конструкцию:
cat /dev/sda | <счетчик> | bzip2 -9 > disk.img
Вывод счетчика в файл или переменную, да в принципе и не важно особо. Главное, чтоб можно было
периодически читать значение счетчика.
Заранее спасибо!
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5399
ОС: Gentoo

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение /dev/random »

В качестве счетчика можно использовать dd без параметров (что аналогично параметрам if=/dev/stdin of=/dev/stdout).
Получая сигнал USR1 (kill -USR1 $pid), он каждый раз будет выводить на stderr количество прошедших через него блоков (не байт!). По умолчанию в блоке 512 байт, и сильно уменьшать это значение не советую - будет отжирать слишком много процессорного времени.
Спасибо сказали:
evgeny2k
Сообщения: 26
ОС: mandriva 2008 spring

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение evgeny2k »

В качестве счетчика можно использовать dd без параметров (что аналогично параметрам if=/dev/stdin of=/dev/stdout).
Получая сигнал USR1 (kill -USR1 $pid), он выведет на stderr количество прошедших через него блоков (не байт!). По умолчанию в блоке 512 байт, и сильно уменьшать это значение не советую - будет отжирать слишком много процессорного времени.

Да, это мысль. Здравая. Спасибо. Уже можно использовать. Но может кто подскажит другие идеи?
Спасибо сказали:
ivze
Сообщения: 39
ОС: Ubuntu

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение ivze »

Код: Выделить всё

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#define buf_length 1024
#define TRUE 1
#define FALSE 0
//The process calculates number of bytes, passed from
//it's stdin to stdout. If an error occurs, it stops and displays the number
//of bytes, it has calculated despite the error. The useful otput is passed
//via stderr.

int main(int argc, char *argv[]){
    int endflag=FALSE;
    ssize_t totalbytes=0;
    char buf[buf_length];
    while(!endflag)
    {
        ssize_t read_now;
        if((read_now=read(0,buf,buf_length))<=0){
            break;//error or end of input:going to finish
        }
        //Sending this all to stdout.
        ssize_t allready_written=0;
        for(;;){
            ssize_t now_written=write(1,buf+allready_written,read_now-allready_written);
            if(now_written<=0){//error :(
                endflag=TRUE;
                break;//going to finish
            }
            allready_written=allready_written+now_written;
            //adding to counter
            totalbytes=totalbytes+now_written;
            if(allready_written==read_now){//time to stop writing
                //and read some again
                break;
            }
        }//for
    }//loop while
    //writing to stderr
    fprintf(stderr,"%i\n",totalbytes);
    exit(0);
}
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5399
ОС: Gentoo

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение /dev/random »

ivze:
1) Эта программа выводит количество байт только в конце (для этого было бы проще использовать
... | tee >(wc -c >/dev/stderr) | ... ), а требуется многократно, по запросу.

2) Вряд ли оптимально для использования в одном скрипте компилировать отдельную C-программу

3) Программы нужно вставлять в блок code или codebox, без отступов ни черта не видно
Спасибо сказали:
ivze
Сообщения: 39
ОС: Ubuntu

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение ivze »

Претензии принимаю (не дочитал треб-ий).
Спасибо сказали:
evgeny2k
Сообщения: 26
ОС: mandriva 2008 spring

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение evgeny2k »

Вариант с dd работает, в принципе то, что нужно, я получил, но не хватает какого-то изящества что-ли :)
В голове что-то крутится, но в полновесную мысль сформироваться не может... Бывает, но пока еще проходит :)
В любом случае, господа, я вам благодарен!
Спасибо сказали:
ivze
Сообщения: 39
ОС: Ubuntu

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение ivze »

Код: Выделить всё

#include<pthread.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#define buf_length 32768
#define TRUE 1
#define FALSE 0
//The process calculates number of bytes, passed from
//it's stdin to stdout. It expects to have file descriptors 3 and 4 to be open.
//It waits for 'n' symbol to come through 3, once it has come, the process
//prints the number of bytes, that have passed through it, to 4.
//
//If the process encounters errors with I/O on 3 or 4 descritors, it shuts down
//the thread, responsible for outputing statistics and continues passing data
//silently.

//*****************************************************************************
//The routine and mutex are used to claim about errors in a thread-safe way.
//The trouble might appear, if two threads wish to use stderr at the same time.
//*****************************************************************************
pthread_mutex_t errmutex;//Shall be initilized in 'main'.
void safe_error_claim(char* string){
    pthread_mutex_lock(&errmutex);
    fprintf(stderr,"%s",string);
    pthread_mutex_unlock(&errmutex);
}
//*****************************************************************************
//The following structures are used to make passig number of calculated
//bytes thread-safe.
//****************************************************************************
ssize_t totalbytes=0;
pthread_mutex_t mutex;  //Synchronization object.
            //shall be initialized in 'main'

//The method is used to thread-safe get the number of passed bytes.
int getTotalBytes(){
    pthread_mutex_lock(&mutex);
    int bytes=totalbytes;//copying
    pthread_mutex_unlock(&mutex);
    return bytes;
}
//The method is used to thread-safe add new bytes to calculator.
void add(ssize_t newbytes){
    pthread_mutex_lock(&mutex);
    totalbytes=totalbytes + newbytes;
    pthread_mutex_unlock(&mutex);
}
//******************************************************************************
//Main methd for the thread, that make answers for statistical requests.
//******************************************************************************
//the sub-methhod is needed by stat_thread_main to perform clean-up
//at termination. The function expects it's argument to be FILE*.
void closef(void* file){
    fclose(
     (FILE*)file
    );
}

//The method does not need any paarmeters, NULL is well enough.
void* stat_thread_main(void* params){
    FILE* out4;//File wrapping for existing file descriptor
    out4=fdopen(4,"w");
    if(out4==NULL){//some error :(
        safe_error_claim("Can't prepare descriptor N4 for writing.");
        return NULL;
    }
    //preparing clean-up handler.
    //The function will be called at this thread's termination (suppose to
    //be stopped via calling ptherad_cancel from the main thread).
    pthread_cleanup_push(&closef, out4);
    //going to loop, taht will break at 'pthread_cancel' call.
    char buf[1];
    ssize_t read_result;
    for(;;){
        read_result=read(3,buf,1);
        if(read_result<=0){//error or end of pipe
            safe_error_claim("troubles with 3 descriptor, stopping statistics.\n");
            break;//going to stop the thread
        }
        switch(*buf){
            case 'n':
                fprintf(out4,"%i\n",getTotalBytes());
            break;
        }
    }//for
    pthread_cleanup_pop(1);//making clean-up, if come here.
    return NULL;
}//stat_thread_main

//******************************************************************************
//Main thread of the process.
//******************************************************************************
int main(int argc, char *argv[]){
    //initializing the mutex.
    pthread_mutex_init(&mutex,NULL/*defaults*/);
    //initializing the errmutex (for careful error output to stderr).
    pthread_mutex_init(&errmutex,NULL/*defaults*/);
    //creating the statistics thread
    pthread_t stat_thread;
    pthread_create(&stat_thread,NULL/*defaults*/,
            &stat_thread_main, NULL/*No arguments*/);//now went away
    //begin passing data
    int endflag=FALSE;
    char buf[buf_length];
    while(!endflag){//The loop breaks, as there is no more data or an error occurs.
        ssize_t read_now;
        if((read_now=read(0,buf,buf_length))<=0){
            break;//error or end of input:going to finish
        }
        //Sending this all to stdout.
        ssize_t allready_written=0;
        for(;;){
            ssize_t now_written=write(1,buf+allready_written,read_now-allready_written);
            if(now_written<=0){//error :(
                endflag=TRUE;
                break;//going to finish
            }
            allready_written=allready_written+now_written;
            //adding to counter
            add(now_written);//thread-safely adding statistical data
            if(allready_written==read_now){//time to stop writing
                //and read some again
                break;
            }
        }//for
    }//loop while
    //So it's time to stop.
    //Stopping statistical thread.
    pthread_mutex_lock(&mutex);//To make sure, the thread is not within the mutex now.
        if(pthread_cancel(stat_thread)!=0){
            safe_error_claim("Something's up with statistical thread.:Can't 'cancel' it.\n");
        }
    pthread_mutex_unlock(&mutex);
    //Releasing mutex.
    pthread_mutex_destroy(&mutex);
    //Joining stat_thread
    if(pthread_join(stat_thread, NULL/*don't need returnvalues*/)!=0){
        safe_error_claim("Can't 'join' statistical thread.\n");
    }
    //Releasing error output mutex.
    pthread_mutex_destroy(&errmutex);
    //All!
    exit(0);
}//main

Модифицированный вариант прогаммы.

Код: Выделить всё

gcc datacalc.c -lpthread -o datacalc

Для компиляции.
Если не пригодится - не страшно. Попросту интересно было написать.
Спасибо сказали:
evgeny2k
Сообщения: 26
ОС: mandriva 2008 spring

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение evgeny2k »

Ну спасибо!!! Думаю сегодня его попробовать... если времени хватит.
А в будущем счетчик неоднократно пригодится, это факт.
Для себя нарисовал аналог на питоне, да вот только не всегда и не везде его использовать получится:(
В общем, всем огромное спасибо за внимание и помощь!!!
Спасибо сказали:
Аватара пользователя
Folderx
Сообщения: 296
ОС: fedora, mandriva

Re: Помогите идеей. Нужен счетчик потока данных. bash

Сообщение Folderx »

Код: Выделить всё

while true; do cat /dev/zero | tee info | cat >>file1; done


проверить как дела

Код: Выделить всё

ls -s --block-size=1 info
Спасибо сказали: