Как посчитать количество байтов в очень большом файле, сгруппировав одинаковые байты?

.INIосновы синтаксиса файлов
[Unit]
Description = My Portal Service
After network.target = my-portal.service

В секции Unitключ должен быть After, а значение — (, например)network.target my-portal.service. У вас есть ключ After network.targetи значение my-portal.service. Этот ключ ничего не значит для systemd, как сказано в сообщении.

Откровенный systemd Дом ужасов всякое

Заставлять службу запускаться после самой себя — нелепо. Но это только верхушка айсберга.

Type = forking
ExecStart = /usr/local/bin/my-portal.sh start
ExecStop = /usr/local/bin/my-portal.sh stop
ExecReload = /usr/local/bin/my-portal.sh reload
…
PATH_TO_LOG="/var/log/egp"
…
PID_PATH_NAME=/var/run/${SERVICE_NAME}-pid
nohup … >> ${PATH_TO_LOG}/${SERVICE_NAME}.out 2>&1&

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

Вам вообще не нужен сценарий оболочки . Вам, конечно, не нужен шаткий и опасный файловый механизм PID, который он пытается использовать. Вам также не нужен ручной -механизм журналирования, который опирается на шаткий механизм logrotate/newsyslog и не может предотвратить заполнение тома вашего диска выводом журнала (, записанным процессом с привилегиями суперпользователя,поэтому во многих случаях он даже съедает зарезервированное для суперпользователя -пространство на аварийном диске ).

Используйте существующие функции диспетчера служб:

#/etc/systemd/system/my-portal.service
[Unit]
Description=My Portal Service
Documentation=https://unix.stackexchange.com/a/434726/5132
After=network.target

[Service]
SyslogIdentifier=my-service
Environment=SERVICE_NAME=my-service
Environment=PATH_TO_TARGET="/opt/apps/egp/stage/my-service/target"
ExecStart=/usr/bin/env java -jar ${PATH_TO_TARGET}/${SERVICE_NAME}.jar server ${PATH_TO_TARGET}/${SERVICE_NAME}.yml

[Install]
WantedBy=multi-user.target

Чтобы прочитать журнал службы, просто используйте journalctlобычным способом. Диспетчер служб отслеживает процессы, запоминая их идентификаторы процессов с момента их создания, и ему не нужен шаткий и опасный файловый механизм PID.

Дополнительная литература

1
31.03.2020, 02:57
4 ответа

Не уверен, что это то решение, которое вы ищете, но я бы просто разделил файл на несколько файлов меньшего размера (, например. через split -b 100MB yourfile), применяя методы, описанные в теме, на которую вы ссылаетесь, а затем суммируя подсчитанные байты в отдельных файлах с помощью программного обеспечения для работы с электронными таблицами по вашему выбору.

0
19.03.2021, 02:31

Соберите маленькую программу на C (или Perl, Python, любую )программу, которая считывает по одному байту за раз и сохраняет итоги. Любой язык, который не является полностью безмозглым в разумной операционной системе, будет выполнять буферизацию и другие операции прозрачно и достаточно эффективно.

1
19.03.2021, 02:31

Поскольку не существует инструмента, который мог бы делать то, что я хочу, я попробовал два самостоятельно -реализованных «скрипта», используя языки, в которых я лучше всего разбираюсь :Python и Java:

Первая попытка :Питон

Следующий скрипт Python 3 работает с файлами любого размера и подсчитывает, как часто встречается каждый байт. К сожалению, даже он работает очень-очень медленно. При использовании Pyhon 3.5 на Raspberry 2 требуется более одной секунды для обработки одного мегабайта!

#!/usr/bin/python3
import sys
file_name = sys.argv[1]
count = 0
block_size = 1048576
byte_count = [0] * 256
with open(file_name, "rb") as f:
    data = f.read(block_size)
    while data:
        for b in data:
            byte_count[b] += 1
        count = count + len(data)
        print("%d MiB"%(count / 1048576))
        data = f.read(block_size)

print("read bytes: {}".format(count))
for i in range(0,255):
    b_c = byte_count[i]
    print("{} : {} ({:f} %)".format('0x%02x'%i, b_c,  b_c / count * 100))

2-я попытка :Java

Для моей второй попытки я использовал Java, и мне кажется, что язык со статической типизацией с JIT, который повторно использует буферы, работает намного эффективнее. Версия Java, работающая на Java 9, была в 40 раз быстрее, чем версия Python, хотя обе версии работают одинаково.

  • Компиляция:javac CountByteValues.java
  • Выполнить:java -cp. CountByteValues <filename>

.

// CountByteValues.java
import java.io.FileInputStream;
import java.io.IOException;

public class CountByteValues {

    public static void main(String[] args) {
        try (FileInputStream in = new FileInputStream(args[0])) {
            long[] byteCount = new long[256];
            byte[] buffer = new byte[1048576];
            int read;
            long count = 0;
            while ((read = in.read(buffer)) >= 0) {
                for (int i = 0; i < read; i++) {
                    byteCount[0xFF & buffer[i]]++;
                }
                count += read;
                System.out.println((count / 1048576) + " MB");
            }

            System.out.println("Bytes read: " + count);
            for (int i = 0; i < byteCount.length; i++) {
                System.out.println(String.format("0x%x %d (%.2f%%)", i, byteCount[i], byteCount[i] * 100f / count));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
0
19.03.2021, 02:31

Как обычно, программа на C будет самой быстрой.
На компьютере, где приведенный вами пример Perl занимает 5 секунд.
Следующий код C занимает всего 0,069 с :

.
#include <stdio.h>

#define BUFFERLEN 4096

int main(){
    // This program reads standard input and calculate frequencies of different
    // bytes and present the frequences for each byte value upon exit.
    //
    // Example:
    //
    //     $ echo "Hello world" |./a.out
    //
    // Copyright (c) 2015 Björn Dahlgren
    // Open source: MIT License

    long long tot = 0; // long long guaranteed to be 64 bits i.e. 16 exabyte
    long long n[256]; // One byte == 8 bits => 256 unique bytes

    const int bufferlen = BUFFERLEN;
    char buffer[BUFFERLEN];
    int i;
    size_t nread;

    for (i=0; i<256; ++i)
        n[i] = 0;

    do {
        nread = fread(buffer, 1, bufferlen, stdin);
        for (i = 0; i < nread; ++i)
            ++n[(unsigned char)buffer[i]];
        tot += nread;
    } while (nread == bufferlen);
    // here you may want to inspect ferror of feof

    for (i=0; i<256; ++i){
        printf("%d ", i);
        printf("%f\n", n[i]/(float)tot);
    }
    return 0;
}

Скопировано изhttps://unix.stackexchange.com/a/209786/232326

0
19.03.2021, 02:31

Теги

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