Можно ли создать временный файл, который будет автоматически удаляться через определенное время, когда он не будет прочитан какой-либо другой программой?

Для этой работы я бы выбрал awk. Код ниже работает только для действительных данных 9 чисел в строке. Пустые строки, строки с числами больше или меньше 9 и строки с буквами игнорируются.

$ cat account
876251251

716126181
888281211
asdferfggggg
666615211
787878787
123456789123
111212134

$ cat customer
876251251
716126181
eeeeeeeee
792342108
792332668
666615211
760332429

791952441
676702288

$ awk '/^[0-9]{9}$/{a[$0]++;b[$0]="found only in " FILENAME}END{for (i in a) if (a[i]==1) print i,b[i]}' account customer |sort -k2
111212134 found only in account
787878787 found only in account
888281211 found only in account
676702288 found only in customer
760332429 found only in customer
791952441 found only in customer
792332668 found only in customer
792342108 found only in customer
0
09.12.2020, 02:02
2 ответа

Основываясь на ответе taiyu с использованием inotifywait, я создал node.jsрешение этой проблемы... Требовалось больше подробностей, чем я ожидал, когда спрашивал об этом. Извините, если это не то место для публикации кода node.js, но асинхронный характер языка упростил мне задачу... Мое решение следующее:

const fs = require('fs');
const spawn = require("child_process").spawn;

const file='/home/user/hugefile.csv';
let counter = 0; // counter used for identifying how many times the file was opened and closed by a different program

const child = spawn('/bin/bash', [ '-c', `inotifywait --format=%e -q -m -e access,close ${file}` ])

child.stdout.on('data', (data) => {
    let line = data.toString().split('\n').filter(item => item); // get events inside a javascript array and filter empty values
    // loop through the inotify events
    line.forEach(function(event) {
        if ( event === "ACCESS" )
            counter++;
        else if ( event === "CLOSE_NOWRITE,CLOSE" )
            counter--;

        // asynchronous function that checks the value of counter after 10 seconds
        async function timer() {
            await sleep(10000);
            console.log(counter);
            if ( counter === 0 ){
                fs.unlinkSync(file); // erase file
                console.log("tmpfile erased!")
                process.exit();
            }
        }
        timer();
    });
});

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

По сути, я использовал inotifywaitкак основу для решения проблемы... Мне просто нужно выполнить этот скрипт после создания временного файла, и он удалит файл после того, как все другие программы закончат чтение файла (после 10 секунд ).


OBS :Проблема, которую я пытаюсь решить с помощью bash, заключается в том, что когда я запускаю функцию как процесс с помощью &, я теряю контроль над новыми значениями глобальных переменных внутри этой функции. Так что я не смог получить состояние counter, используя ту же логику, которую я использовал для node.js... Если кто-то знает обходной путь для этого, не стесняйтесь писать в комментариях здесь.:)

0
18.03.2021, 22:44

Используя inotifywait, вы можете добавить в свои скрипты, которые обращаются к файлу, следующее.

if ! inotifywait $FILE -t $SECONDS >/dev/null 2>&1
then rm $FILE
fi &

Сценарий порождает процесс, ожидающий, пока кто-то не получит доступ к $FILE.
если что-то происходит, он ничего не делает и выходит.
если время ожидания истекло после $SECONDS, он удалит файл

альтернативно используя отдельный скрипт, который вы запускаете при создании файла

while inotifywait $FILE -t $SECONDS >/dev/null 2>&1
do sleep 1
done
rm $FILE

он будет зацикливаться при доступе к файлу,
если ничто не обращается к нему в течение тайм-аута, он ломает и удаляет файл.

0
18.03.2021, 22:44

Теги

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