AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / computer / 问题 / 1631567
Accepted
Private_Citizen
Private_Citizen
Asked: 2021-03-08 10:28:00 +0800 CST2021-03-08 10:28:00 +0800 CST 2021-03-08 10:28:00 +0800 CST

在linux中替换活动文件的最佳方法(mv/cp)?

  • 772

我正在制作一个用于更新活动服务的文本包含/conf 文件的脚本。该脚本将首先将更改写入临时文件。完成后,用临时文件替换包含文件,考虑到服务处于活动状态,使用,cp还是其他更好?我不清楚它如何与保留文件句柄的程序一起工作。mvecho >

如果答案是如果有东西持有文件句柄是不可能的,那么最好。假设服务只是打开、读取、关闭。替换文件的最安全方法是什么?

差点忘了,我使用 PHP 作为脚本,使用内置的 php move/copy 方法与 bash mv/有区别cp吗?

linux cp
  • 2 2 个回答
  • 395 Views

2 个回答

  • Voted
  1. harrymc
    2021-03-08T10:59:22+08:002021-03-08T10:59:22+08:00

    这里有两个概念:文件名和文件数据。

    如果一个文件被 删除rm,它就会失去它的名字,但是直到最后一个打开它的程序停止,它的数据才会被释放。但是,如果文件以独占方式打开,则无法对其进行操作。

    因此,如果无法删除该文件,一个已知的解决方法是重命名它。

    在您的情况下,如果其他程序不断打开文件,您可能会发现自己处于删除文件但没有复制新文件的情况,因此其他程序会发现文件丢失。

    如果丢失的文件不是问题,我会这样做:

    • 将文件重命名为某个临时名称
    • 将替换文件复制到其位置
    • 删除临时名称。

    如果此方法不适合您,您将需要使用信号量机制。您可以使用 lockfile 命令作为两个程序之间的锁。这个例子来自man页面:

    ...
    lockfile important.lock
    ...
    access_"important"_to_your_hearts_content
    ...
    rm -f important.lock
    ...
    
    • 0
  2. Best Answer
    Kamil Maciorowski
    2021-03-08T14:48:34+08:002021-03-08T14:48:34+08:00

    分析

    在程序(例如,所讨论的服务)获得文件句柄后,该句柄引用由其在文件系统中的 inode 编号标识的相同文件,该文件包含该文件。文件的路径名无关紧要。

    如果文件在文件系统中被重命名或移动,路径名将会改变。如果文件被取消链接(删除)或移动到另一个文件系统(此操作实际上是复制,然后取消链接),路径名将消失。这些都不重要。即使链接计数降至零,句柄也将保持有效(这意味着文件系统中不再有指向该文件的路径名)。只有当链接计数为零并且没有使用该文件时,文件系统才会真正摆脱该文件。

    如果您使用whatever … > the_file或向文件写入cp foo the_file内容,则文件的内容将发生变化,但“文件”仍将表示其 inode 编号未更改的文件。旧句柄将引用修改后的文件。握住手柄的程序将能够立即看到更改。

    这种方法的一个大问题是程序可能偶然对处于无效状态的文件进行操作。“无效”是指“程序逻辑无效”,而不是“文件系统损坏”。例如>首先截断文件,所以它的大小为零,然后才写入一些东西。程序可能会发现文件为空,但程序的逻辑绝不应该为空。通常,您可以覆盖或修改而不截断或在末尾截断(到所需的大小),因此在某些时候文件可能是一半旧的,一半是新的。无论如何,程序在任何给定时刻都无法轻易知道文件是否完整且有效。当涉及到配置文件时,一种理智的方法是允许程序假定文件是有效的,而不是以这种方式更新配置。

    另一种更新方式是使用mv. 当你这样做mv foo the_file并且两者foo都the_file在同一个文件系统中时,the_file会被原子地替换,结果是name 下的foo前者的内容。foothe_file

    这里的“原子”意味着如果任何程序the_file在任何时候重新打开,那么它将获得一个文件句柄,该句柄将导致旧内容或新内容。无法发现混合状态或以其他方式损坏的内容,因为此类内容从不存在。

    将其视为硬链接foo到the_file(此行为将the_file文件名从其旧 inode 切换到 of foo)然后取消链接foo。在这种情况下,“原子地”并不意味着您不能发现foo和更新的目标文件同时存在。它只是意味着the_file总是要么全旧要么全新,没有中间状态。

    笔记:

    • mv在文件系统之间就像cp+ unlink,它的行为就像cp(上面讨论过的)。
    • 请参阅我的 fs 上是mv原子的吗?

    因为the_file文件名现在与另一个 inode 相关联(foo在它被取消链接之前指向的那个),the_file从之前的所有文件句柄mv仍然指向旧文件。即使没有路径名,旧文件仍然存在于文件系统中。它可以读取、写入;它可以增长。这是一个单独的文件,与您现在看到的不同the_file。它的不同之处与the_file之前的不同foo。

    这意味着如果以这种方式更新由服务保持打开的配置文件将是徒劳的,除非服务通过路径重新打开它并再次读取配置。

    在不切换到另一个 inode 的情况下更新时(例如使用cp),您需要一些机制来告诉服务停止使用文件(这可能包括也可能不包括关闭文件)并告诉它稍后继续使用文件。否则存在服务使用文件的某些中间状态的风险。最基本的机制就是停止服务并在准备好时启动。该服务可能支持某种机制来执行此操作而无需停止,但我不会指望它。

    一般来说,允许中间状态存在于文件系统中是有风险的。如果发生电源故障或其他中断(例如 rash Ctrl+ C),您可能会得到无效文件。我已经将“无效”解释为“程序逻辑无效”,而不是“在文件系统中损坏”,但后来我们谈论的是文件只是暂时无效的情况,它最终会有效。现在我们正在讨论一种无效状态仍然存在的情况,因为将一个有效状态转换为另一个有效状态的过程在中间终止。

    mv允许您避免无效状态。mv你肯定需要一些机制来告诉服务通过路径重新加载文件;否则它将坚持旧文件。最基本的机制是重启服务。该服务可以支持替代方案,例如sshd重新读取其配置SIGHUP,而无需重新启动。这是正道。

    注意很多取决于服务的行为方式:

    • 服务可能会读取文件一次,自行配置并且不再读取,除非重新启动或被要求(如果支持)。
    • 或者它有时可能会出于某种原因使用相同的文件句柄再次读取文件。
    • 或者它有时会因为某种原因重新打开而再次阅读。
    • 它可能会监视文件并在文件更改时重新读取它。一般来说,很难判断更改何时完成,所以我会说这种方法是有缺陷的。
    • 该服务可能会监视文件名并在它开始指向另一个 inode 时重新读取它。这适用mv于更新方法,但仅适用于单个文件。如果配置可以存储在许多文件中,那么服务应该只在需要时重新读取它。您可以自动更新任何单个文件,mv但不能更新整个多文件配置。

    明确的回答

    替换文件的最安全方法是什么?

    绝对mv在同一个文件系统中。如果您希望它在不重新启动的情况下使用新文件,则需要该服务的支持。我不知道您的服务表现如何。

    使用内置的 PHP 移动/复制方法与 Bash mv/有区别cp吗?

    (旁注:你在 Bash 中调用的是mv与cpBash 无关的独立可执行文件。)

    我不知道PHP,我无法回答这个问题。我认为它的 move 方法没有理由不是原子的,但我可能错了。我希望此答案中的信息对您自己的研究有所帮助。现在你知道要注意什么了。

    • 0

相关问题

  • 如何让我的 Linux 机器看起来像是在运行 Windows?

  • 对于 cp 或 mv,是否有等同于 cd - 的东西?

  • 以 root 身份运行 docker 容器

  • 如何在域和 Linux 活动目录中启用指纹传感器

  • 如何在CentOS 7 中将Ctrl+C 永久更改为Ctrl+K?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何减少“vmmem”进程的消耗?

    • 11 个回答
  • Marko Smith

    从 Microsoft Stream 下载视频

    • 4 个回答
  • Marko Smith

    Google Chrome DevTools 无法解析 SourceMap:chrome-extension

    • 6 个回答
  • Marko Smith

    Windows 照片查看器因为内存不足而无法运行?

    • 5 个回答
  • Marko Smith

    支持结束后如何激活 WindowsXP?

    • 6 个回答
  • Marko Smith

    远程桌面间歇性冻结

    • 7 个回答
  • Marko Smith

    子网掩码 /32 是什么意思?

    • 6 个回答
  • Marko Smith

    鼠标指针在 Windows 中按下的箭头键上移动?

    • 1 个回答
  • Marko Smith

    VirtualBox 无法以 VERR_NEM_VM_CREATE_FAILED 启动

    • 8 个回答
  • Marko Smith

    应用程序不会出现在 MacBook 的摄像头和麦克风隐私设置中

    • 5 个回答
  • Martin Hope
    Saaru Lindestøkke 为什么使用 Python 的 tar 库时 tar.xz 文件比 macOS tar 小 15 倍? 2021-03-14 09:37:48 +0800 CST
  • Martin Hope
    CiaranWelsh 如何减少“vmmem”进程的消耗? 2020-06-10 02:06:58 +0800 CST
  • Martin Hope
    Jim Windows 10 搜索未加载,显示空白窗口 2020-02-06 03:28:26 +0800 CST
  • Martin Hope
    v15 为什么通过电缆(同轴电缆)的千兆位/秒 Internet 连接不能像光纤一样提供对称速度? 2020-01-25 08:53:31 +0800 CST
  • Martin Hope
    andre_ss6 远程桌面间歇性冻结 2019-09-11 12:56:40 +0800 CST
  • Martin Hope
    Riley Carney 为什么在 URL 后面加一个点会删除登录信息? 2019-08-06 10:59:24 +0800 CST
  • Martin Hope
    zdimension 鼠标指针在 Windows 中按下的箭头键上移动? 2019-08-04 06:39:57 +0800 CST
  • Martin Hope
    jonsca 我所有的 Firefox 附加组件突然被禁用了,我该如何重新启用它们? 2019-05-04 17:58:52 +0800 CST
  • Martin Hope
    MCK 是否可以使用文本创建二维码? 2019-04-02 06:32:14 +0800 CST
  • Martin Hope
    SoniEx2 更改 git init 默认分支名称 2019-04-01 06:16:56 +0800 CST

热门标签

windows-10 linux windows microsoft-excel networking ubuntu worksheet-function bash command-line hard-drive

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve