如何在RAM中制作一个临时文件?


29

我有一个脚本,会将其输出传递给|tee scriptnameYYMMDD.txt。在生成输出的for循环的每个循环之后,我将使用反转文件内容,tac scriptnameYYYYMMDD.txt > /var/www/html/logs/scriptname.txt以便在浏览器窗口中以最新行显示日志输出。

我将有几个脚本并行执行此操作。我正在尝试最小化磁盘活动,因此输出|tee scriptnameYYYYMMDD.txt到RAMdisk最好。mktemp/tmp文件夹中创建一个文件,但该文件似乎不在磁盘上。


它必须是ramfs或tmpfs(秒更好)。检查这样的fs是否已经安装在您的系统上,如果可以,则可以使用它。如果否,则需要安装它。
彼得说恢复莫妮卡

我会更新fstab,以便安装一tmpfs/tmp,然后重新启动计算机。
卡巴斯德,2015年

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 for循环结束时,我 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可能会影响某些文件,但是可以接受。
user208145

更新我的进度:我在/ ramdisk上安装了1 GB tmpfs卷。我有文件通过FTP进入用户主文件夹。它们被移至子文件夹/ ramdisk / queues / xyz /进行处理,然后被删除。启动时,我有一个脚本可以在/ ramdisk下重新创建所需的目录结构。这将导致传入文件的磁盘活动最少。到目前为止,我认为减少这些脚本的磁盘I / O的唯一其他方法是,在将任何文件通过FTP传入这些用户文件夹之前,在启动时创建的tmpfs中创建这些用户文件夹。谢谢大家
user208145

Answers:


22

您可以挂载tmpfspartititon并将文件写入那里:

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

该分区现在限制为500 MB。如果您的临时文件大于500 MB,则会发生错误:no space left on device。但是,当您指定比系统RAM更大的空间时,这并不重要。tmpfs也会使用交换空间,因此您不能强制系统崩溃ramfs

您现在可以将文件写入/mountpoint

command | tee /mountpoint/scriptnameYYYYMMDD.txt

3
size=[num]%也很好-可以将tmpfs限制为可用内存的百分比。如果命令并非总是针对同一台(真实/虚拟)计算机,则通常更容易这样做。方便的是tmpfs不会丢弃带有w /的内容-o remount,size=newsize
mikeserv

1
由于各地的bash脚本的问题旋转,这是我们没有理由假定由root身份运行,你可以指定一个人是否能得到周围mount不允许非root用户使用-t还是-o?也就是说tmpfs,如果系统上还没有合适的文件系统,那么一个构建脚本如何使用(或以任何其他方式的RAM)保存磁盘操作?
Jonathan Y.

不好回答。如果您不是root用户,将失败。
Alex

11

在Ubuntu上尝试一下:

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

3
写入的稳定性如何/run/shm/chmod如果需要,我可以将更改应用于临时文件吗?我注意到文件夹的模式位与/tmp文件夹相同。谢谢。
user208145

1
至于其他目录,在/run/shm(符号链接到/dev/shm)中生成的文件mktemp的默认权限也为-rw-------(600),如果需要,可以使用进行更改sudo chmod
KrisWebDev '16

9

以下的答案被调查以前的答案,并在这个问题上的信息发现,这里并不会被发现,没有他们。对他们表示敬意。

在我的linuxmint系统上(我会假设大多数基于ubuntu的系统,也可能基于debian),有一个用户拥有的tmpfs自动挂载在 /run/user/1000/

使用df -T检查。

11:41:11 jesse @ Limbo:〜$ df -T
文件系统类型1K块已使用可用用法已安装%
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%/运行/锁定
无tmpfs 15920584 848 15919736 1%/ run / shm
无tmpfs 102400 12 102388 1%/运行/用户
/ 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命名。我们可以使用id -usee 获取用户ID,以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选项的命令在此tempfilesystem中创建临时文件和目录,从而在RAM中创建临时文件。

按照此处给出的建议我首先创建一个临时目录,然后在其中创建临时文件:

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在每个使用systemd的linux上都可用,因此它不仅在基于debian的系统上可用,而且在大多数其他linux发行版中也可用。如果不是,则应改用/ tmp。您可以使用变量$ XDG_RUNTIME_DIR简化命令,该变量已经为每个用户保留了正确的目录。有关更多信息,请检查例如以下答案:unix.stackexchange.com/questions/162900/…–
Alex

1
使用mkstemp超过mktemp!原因来自:linux.die.net/man/3/mktemp:错误部分:“ ...每次使用mktemp()都存在安全风险,mkstemp(3)避免了竞争。”
Alex

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 ) 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.