Windows下如何共享日志文件?

2023-12-11

我有几个不同的进程,我希望它们都记录到同一个文件。这些进程在Windows 7系统上运行。有些是 python 脚本,有些是cmd批处理文件。

在 Unix 下,你只需让每个人都以追加模式打开文件并写入即可。只要每个进程写的少于PIPE_BUF单个消息中的字节,每个write将保证调用不会与任何其他调用交错。

在 Windows 下有没有办法实现这一点?这种天真的类 Unix 方法失败了,因为默认情况下 Windows 不喜欢多个进程同时打开一个文件进行写入。


可以将多个批处理进程安全地写入单个日志文件。我对 Python 一无所知,但我想这个答案中的概念可以与 Python 集成。

Windows 最多允许一个进程在任何时间点打开一个特定文件进行写访问。这可用于实现基于文件的锁定机制,以保证事件在多个进程之间序列化。看https://stackoverflow.com/a/9048097/1012053 and http://www.dostips.com/forum/viewtopic.php?p=12454举一些例子。

由于您要做的只是写入日志,因此您可以使用日志文件本身作为锁。日志操作封装在一个子例程中,该子例程尝试以附加模式打开日志文件。如果打开失败,例程将循环返回并重试。一旦打开成功,日志就会被写入然后关闭,并且例程返回给调用者。该例程执行传递给它的任何命令,并且例程中写入 stdout 的任何内容都将重定向到日志。

下面是一个测试批处理脚本,它创建 5 个子进程,每个子进程写入日志文件 20 次。写入是安全交错的。

@echo off
setlocal
if "%~1" neq "" goto :test

:: Initialize
set log="myLog.log"
2>nul del %log%
2>nul del "test*.marker"
set procCount=5
set testCount=10

:: Launch %procCount% processes that write to the same log
for /l %%n in (1 1 %procCount%) do start "" /b "%~f0" %%n

:wait for child processes to finish
2>nul dir /b "test*.marker" | find /c "test" | >nul findstr /x "%procCount%" || goto :wait

:: Verify log results
for /l %%n in (1 1 %procCount%) do (
  <nul set /p "=Proc %%n log count = "
  find /c "Proc %%n: " <%log%
)

:: Cleanup
del "test*.marker"
exit /b

==============================================================================
:: code below is the process that writes to the log file

:test
set instance=%1
for /l %%n in (1 1 %testCount%) do (
  call :log echo Proc %instance% says hello!
  call :log dir "%~f0"
)
echo done >"test%1.marker"
exit

:log command args...
2>nul (
  >>%log% (
    echo ***********************************************************
    echo Proc %instance%: %date% %time%
    %*
    (call ) %= This odd syntax guarantees the inner block ends with success  =%
            %= We only want to loop back and try again if redirection failed =%
  )
) || goto :log
exit /b

以下输出表明每个进程的所有 20 次写入均成功

Proc 1 log count = 20
Proc 2 log count = 20
Proc 3 log count = 20
Proc 4 log count = 20
Proc 5 log count = 20

您可以打开生成的“myLog.log”文件以查看写入是如何安全交错的。但输出太大,无法在此发布。

通过修改 :log 例程使其在失败时不会重试,很容易证明来自多个进程的同时写入可能会失败。

:log command args...
>>%log% (
  echo ***********************************************************
  echo Proc %instance%: %date% %time%
  %*
)
exit /b

以下是“破坏” :log 例程后的一些示例结果

The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
The process cannot access the file because it is being used by another process.
Proc 1 log count = 12
Proc 2 log count = 16
Proc 3 log count = 13
Proc 4 log count = 18
Proc 5 log count = 14
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows下如何共享日志文件? 的相关文章

随机推荐

  • WooCommerce 中特定产品变体的自定义后缀

    我正在尝试为可变商品的价格添加后缀 它只需要在选择该特定项目时显示 我尝试了 stackoverflow 中的一些不同代码 但所有代码都将后缀添加到所有变量 而不仅仅是我需要的变量 目前我正在使用以下代码 但它给出了一个严重错误 致命错误
  • C# 和正则表达式 - 无法识别的分组构造

    目前正在研究客户端 服务器应用程序的论文 如果服务器接收到这样的信息 我遇到了一个障碍 ProToCooL unknown DESKTOP 29COFES 10 20 9 53 Hewlett Packard 179C PCWJA001X3
  • 匹配带有空格的不区分大小写的精确短语

    如果我有一个字符串 Hello I went to the store today 我有一系列比赛 perfectMatches array i went store today 它应该与这两者相匹配 数组可能会变得很大 所以我更愿意在 1
  • 如何在java中执行1个命令x次

    我想问一下如何多次执行1个命令 例如这段代码 System out println Hello World 我想运行 500 次 我该怎么做 谢谢 问候 威廉姆斯 使用 Java 8 Streams 你可以这样做 IntStream ran
  • 在 Objective-C 中将 NSArray 转换为 NSString

    我想知道如何转换NSArray Apple Pear 323 Orange 到一个字符串Objective C NSString result array valueForKey description componentsJoinedBy
  • Task == 是懒惰的吗?

    public Data GetCurrent Credentials credentials var data new Lazy
  • 无法领取 PosPrinter

    我有一台 TM T20 Epson 我正在使用此代码尝试打印 Hello Printer 消息 并且我不断跟踪 PosPrinter 的一些特性 public void ImprintHelloPrinter The Explorer Po
  • 从 ViewModel 打开一个窗口

    我试图使我的 WPF 应用程序解耦 因此我做了类似的事情 视图的项目 ViewModel 的项目 In the mainwindow我在按钮和按钮之间进行了绑定OpenChildWindowCommand它位于 ViewModel DLL
  • PHP如何执行命令

    我正在尝试使用 LibreOffice 将电子表格转换为另一种格式 当我从控制台执行命令时 它工作正常 但当我使用 exec 或 system 从 PHP 执行命令时 它不起作用 它没有显示任何错误或任何东西 它只是默默地失败 如果我尝试执
  • 如何公开用户控件内的 GridView 控件的列集合

    请参阅编辑 我希望能够在使用用户控件的 aspx 中执行此操作
  • NetSuite 保存搜索公式以将其他两列的结果相乘

    我当前有一个保存的搜索 用于填充项目列表 我当前的结果是标准 NetSuite 字段 即 名称 描述 类型 平均成本 和 可用 我正在尝试为公式添加另一列 该公式将平均成本乘以可用成本 得出可用 SOH 的值 在保存的搜索结果中添加一个新的
  • 使用 SwiftUI 显示多个 VNRecognizedObjectObservation 边界框时偏移错误

    我正在使用 Vision 来检测物体 然后得到 VNRecognizedObjectObservation 我在显示标准化矩形之前对其进行转换 let transform CGAffineTransform scaleX 1 y 1 tra
  • MaltParser 在 Python NLTK 中不工作

    我无法让 Maltparser 与 Python NLTK 一起使用 到目前为止 这是我的代码 import nltk os environ MALT PARSER C Python34 maltparser 1 8 1 os enviro
  • 适用于 Android 的 Firebase Admin SDK,未找到方法

    我正在构建一个由 Firebase 应用程序支持的 Android 应用程序 并且我希望能够创建一个可以编辑或删除其他用户帐户的管理员帐户 如果我理解正确 Firebase Admin SDK 应该允许我执行此操作 所以我按照说明进行操作h
  • 安装 IntelliJ IDEA 后从控制台运行简单的 hello world

    我在Mac上安装了IntelliJ IDEA并编写了最简单的Kotlin程序 fun main args Array
  • 为什么本站的ECC-DH对称密钥与OpenSSL不一样

    我在用 本网站的 Javascript 库和 OpenSSL Ruby 用于计算椭圆曲线 Diffie Hellman 的对称密钥 然而 从我的结果来看 OpenSSL Ruby 仅生成了一个密钥 这与网站上具有 X 和 Y 对称密钥的密钥
  • Azure Function App无法加载IOptionsFormatter

    我有一个 C Azure Function App 我正在尝试在本地运行 几个月前它工作得很好 但现在失败了 原因如下 主机发生错误Microsoft Azure WebJobs Extensions Storage 无法从程序集 Micr
  • 从 Cray Fortran 获取当前主机名

    有人知道如何从 Cray Fortran 程序获取当前主机名吗 我基本上想要 UNIX 的输出gethostname 在浏览 Craydocs 页面后 我发现 PXF 函数似乎不包含此信息 Wirawan Cray Fortran 在现代
  • 如何从linkedin jsapi获取公司ID

    我试图使用 jsapi 从 linkedin 获取公司 ID iam 使用下面的 url 公司搜索 公司 id 名称 关键字 ibm 20oracle 20infosys 我得到了其他一些公司的 ID companies count 10
  • Windows下如何共享日志文件?

    我有几个不同的进程 我希望它们都记录到同一个文件 这些进程在Windows 7系统上运行 有些是 python 脚本 有些是cmd批处理文件 在 Unix 下 你只需让每个人都以追加模式打开文件并写入即可 只要每个进程写的少于PIPE BU