Як зробити тимчасовий файл в оперативній пам’яті?


29

У мене є сценарій, який передасть свій вихід |tee scriptnameYYMMDD.txt. Після кожного циклу циклу for, в якому генерується висновок, я зміню вміст файлу, tac scriptnameYYYYMMDD.txt > /var/www/html/logs/scriptname.txtщоб вивід журналу був видно у вікні браузера з останніми рядками вгорі.

У мене буде декілька сценаріїв, які роблять це паралельно. Я намагаюся мінімізувати активність диска, тому |tee scriptnameYYYYMMDD.txtнайкращим буде вихід з RAMdisk. mktempстворює файл у /tmpпапці, але, схоже, це не на диску.


Це повинен бути ramfs або tmpfs (другий краще). Перевірте, чи такий FS вже встановлений у вашій системі, якщо так, ви можете використовувати це. Якщо ні, потрібно встановити її.
Peterh каже відновити Моніку

Я б оновити fstab, щоб змонтувати tmpfsна , /tmpа потім перезавантажити машину.
kasperd

1
ви можете розглянути можливість поступового tailзавантаження файлів (або ініціювання його через CGI на запит чи щось), а не tacінг.
mikeserv

Це, здається, працює в тестуванні (вибачте за зменшене форматування): TEMPPATH="/ramdisk" LOGPATH="/var/www/html/log" ... echo <various calls to echo> | tee -a $TEMPPATH/moveKRT$(date '+%Y%m%d').txt ... після закінчення циклу, я маю на cp $TEMPPATH/moveKRT$(date '+%Y%m%d').txt $LOGPATH/moveKRT$(date '+%Y%m%d').txt tac $TEMPPATH/moveKRT$(date '+%Y%m%d').txt > $LOGPATH/moveKRT.txt увазі незначну можливість, що зміна з 23: 59: 59,999 до 00:00: 00 може вплинути на деякі файли, але шанс прийнятний.
користувач208145

Повідомлення про мій прогрес щодо цього: у мене є об'єм tmpfs об'ємом 1 ГБ, встановлений на / ramdisk. У мене є файли, які надходять у домашні папки користувача через FTP. Вони переміщуються до підпапки / ramdisk / черги / xyz / для обробки та видаляються згодом. Під час запуску у мене є сценарій, який заново створює потрібну структуру каталогу під / ramdisk. Це повинно призвести до мінімальної активності диска для вхідних файлів. Поки єдиним іншим способом, як я бачу, зменшити введення / виведення диска для цих скриптів, було б створити ці користувацькі папки в форматі tmpfs, створеному під час запуску, до того, як будь-які файли заходять через FTP до цих папок користувача. Дякую всім.
користувач208145

Відповіді:


22

Ви можете встановити tmpfspartititon і записати туди файл:

mount -t tmpfs -o size=500m tmpfs /mountpoint

Зараз цей розділ обмежений 500 Мб. Якщо ваш тимчасовий файл стає більше , ніж 500 МБ виникає помилка: no space left on device. Але це не має значення, коли ви вкажете більший обсяг простору, ніж у вашій системній оперативній пам'яті. tmpfsтакож використовується простір swap, тому ви не можете змусити збої системи на відміну від ramfs.

Тепер ви можете написати свій файл у /mountpoint:

command | tee /mountpoint/scriptnameYYYYMMDD.txt

3
size=[num]%також добре - tmpfs може бути обмежений відсотком наявної пам'яті. Зазвичай це простіше, якщо команди не завжди націлені на один і той же (реальний / віртуальний) апарат. Також зручно те, що tmpfs не скидає вміст w / -o remount,size=newsize.
mikeserv

1
Оскільки питання обертається навколо сценарію bash, який ми не маємо причин вважати, що він працює під коренем, ви можете вказати, чи можна було б обійти, mountне дозволяючи користувачам, що не входять до програми root, -tабо -o? Тобто, як можна створити сценарії, які використовують tmpfs(або ОЗУ будь-яким іншим способом) для економії на дискових операціях, якщо у системі вже не існує відповідної файлової системи?
Джонатан Ю.

Недобра відповідь. Вийде з ладу, якщо ви не корінь.
Олексій

11

Спробуйте це за допомогою Ubuntu:

ramtmp="$(mktemp -p /dev/shm/)"
tac scriptnameYYYYMMDD.txt > "$ramtmp"

3
наскільки стабільно пишеться /run/shm/? Чи можу я застосувати chmodзміни до тимчасового файлу, якщо потрібно? Я помітив, що біти режиму папки ідентичні /tmpпапці. Спасибі.
користувач208145

1
Що стосується інших каталогів, файли, згенеровані в /run/shm(symlink to /dev/shm), mktempтакож мають дозвіл за замовчуванням -rw-------(600), і ви можете змінити його, якщо потрібно, за допомогою sudo chmod.
KrisWebDev

9

Наступна відповідь була виявлена ​​шляхом дослідження попередніх відповідей та інформації в цьому запитанні тут, і без них їх не було б знайдено. Кудо до них.

У моїй системі linuxmint (і я вважаю, що більшість систем, що базуються на ubuntu, і, можливо, також на базі Debian), є tmpfs, що належить користувачеві, автоматично встановлений на /run/user/1000/

Використовуйте df -Tдля перевірки.

11:41:11 jesse @ Limbo: ~ $ df -T
Файлова система Тип 1К-блоків Використовується Доступне використання% Встановлено
udev devtmpfs 15904812 4 15904808 1% / dev
tmpfs tmpfs 3184120 1700 3182420 1% / пробіг
/ dev / sdb2 ext4 14248880 11464788 2037240 85% /
немає tmpfs 4 0 4 0% / sys / fs / cgroup
немає tmpfs 5120 0 5120 0% / run / lock
немає tmpfs 15920584 848 15919736 1% / пробіг / шм
відсутність tmpfs 102400 12 102388 1% / run / user
/ dev / sdb3 ext4 100861352 90755700 4959136 95% / mnt / дані

Під /run/user/системою є каталог для кожного звичайного користувача в системі

12:07:35 jesse@Limbo:~$ ls -l /run/user
total 0
drwx------ 2 root  root   40 Aug  7 09:50 0
drwx------ 8 jesse jesse 180 Aug  7 11:38 1000

Ці каталоги названі іменами відповідного користувача. Ми можемо отримати ідентифікатор користувача, id -uщоб man idотримати детальну інформацію про цю команду.

12:07:43 jesse@Limbo:~$ ls -l /run/user/$(id -u)
total 0
drwx------ 2 jesse jesse  60 Aug  7 09:50 dconf
dr-x------ 2 jesse jesse   0 Aug  7 09:50 gvfs
drwx------ 2 jesse jesse  80 Aug  7 09:50 pulse
lrwxrwxrwx 1 root  root   17 Aug  7 09:50 X11-display -> /tmp/.X11-unix/X0

Потім ми можемо використовувати mktempкоманду з --tmpdirможливістю створення тимчасових файлів і каталогів у цій tempfilesсистемі, створюючи тимчасові файли в ОЗП.

Дотримуючись наведених тут порад, спершу я створюю тимчасовий каталог, а потім створюю свої тимчасові файли:

mydir=$(mktemp -dt "$(basename $0).XXXXXXXX" --tmpdir=/run/user/$(id -u))

створити тимчасову папку , /run/user/1000/bash.w42BYxbG/то

myfile=$(mktemp -t "$(basename $0).XXXXXXXX" --tmpdir=$mydir)

створити в ньому темпфіл.

Це робить очищення цих файлів простим, оскільки все, що мені потрібно зробити rm -r $mydir.

За замовчуванням всі ці файли належать та читаються лише користувачем, який їх створив.

Примітка. $(basename $0)Частина команди витягує ім'я сценарію / процесу, який виконав mktemp. Якщо у мене є сценарій, /home/jesse/scripts/myScript.shвін $(basename $0)повертається myScript.shпри виконанні цього сценарію. Таким чином, вищезазначені команди створювали б /run/user/1000/myScript.sh.w42BYxbG/і /run/user/1000/myScript.sh.w42BYxbG/myScript.sh.BCzSmq06відповідно.


/run/user/1000доступний на кожному Linux, який використовує systemd, тому він доступний не тільки в системах на базі debian, але і в більшості інших дистрибутивів Linux. Якщо ні, натомість слід використовувати / tmp. Ви можете спростити свої команди, використовуючи змінну $ XDG_RUNTIME_DIR, яка вже зберігає правильний каталог для кожного користувача. Для отримання додаткової інформації перевірте, наприклад, цю відповідь: unix.stackexchange.com/questions/162900/…
Alex

1
Використовуйте mkstemp над mktemp !! Причина: linux.die.net/man/3/mktemp : у розділі Помилки "... кожне використання mktemp () - це ризик безпеки, гонки уникає mkstemp (3)".
Олексій

0

Як я розумію, це ще є: (1) дійсно зберегти перевернутий файл на диск, який буде подано в браузер (примітка: це може бути TMPFS і т.д., як і всі інші відповіді вже докладно); але, (2) уникайте запису першого файлу tmp на диск з оригінальним висновком; і, тим не менше, (3) все ще відображає вихідний вихід для stdout.

Якщо так, то наступні можуть задовольнити ваші потреби, використовуючи заміну процесу bash (тобто, в основному, названу трубу):

command | tee >( tac > /var/www/html/logs/scriptname.txt )

Зауважте, що це безперервно друкує вихід на stdout, і коли команда закінчується (коли цикл закінчується), повертає цей вихід і записує його у вихідний файл. Ілюструється за допомогою наступного, яке друкує один рядок в секунду, а після закінчення файл /tmp/foo.txtмістить зворотні рядки:

i=0
while [ $i -lt 10 ]; do
    ((i = i+1))
    echo "==$i== $(date)"
    sleep 1
done | tee >( tac >> /tmp/foo.txt ) 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.