在 [1] 提交 gpu 申请之后,想让服务器(linux)在申上时候发个消息回本地(windows),弹个窗提醒我,写个 .txt 文件用 scp 传回来再用 start 命令打开就行,问题是服务器不知道怎么调用本地命令(如果不是手动连 ssh,而是程序调)。
于是仿照 [2] 的思路,在本地写一个 daemon,服务器写好 .txt 信息传回来之后,再传一个 .bat 打开该 .txt 就行。本篇是本地的 daemon,是接收端;服务器那段也要一个发送端的程序,以后再说。
- 执行 .bat 先重命名前,防止重复执行,这里是在文件名前加了一个自定义的前缀
%RUN_PREFIX%。 - 借助一个额外的脚本 _caller.bat 支持多进程(本来用
start /b cmd /c "%P%\%%f & del %%f",但有点问题),执行 .bat 后删除:
用@echo off if (%1) == () exit call %1 del %1:build_caller创建,call _caller.bat foo.bat调用。 start "" /b <CMD>后台执行命令,见 [3]。- 死循环
for /l %%_ in () do (...),见 [6]。用exit /b和goto :eof退出不了,exit也会卡住(挂起?),可以用 [6](人为报错)或 [7](模拟 Ctrl-C)的方案。 - 用
:validate函数做简单身份验证:在 .bat 第一行写上REM <KEY>,配合自定义的%KEY%,用来验证该 .bat 确实是自己写的,防止被人搞。函数返回值见 [9]。 - 为防文件名有空格,用
""括住;:validate中for的usebackq标记也是防空格,见 [10]。
Code
- 调用:
daemon.bat或daemon.bat <探测路径>。探测路径就是放要执行的 .bat 的目录,同 [2],默认是.。
REM daemon.bat
@echo off
setlocal enabledelayedexpansion
set THIS=%~nx0
set SLEEP=2
set /a TIMEOUT = 7
set RUN_PREFIX=__running__
set "KEY=REM iTom"
title %THIS%
REM detecting path
if (%1) == () (
REM default to current path
set P=pool
) else (
REM `daemon.bat <DETECT_PATH>`
set P=%1
)
call :build_caller
set timer=0
for /l %%_ in () do (
set cnt=0
for %%f in (%P%\*.bat) do (
REM echo %%f
set fname=%%~nxf
if "!fname!" NEQ "%~nx0" (
if "!fname!" NEQ "_caller.bat" (
call :validate "%%~dpnxf" is_valid
if !is_valid! EQU 1 (
if "!fname:%RUN_PREFIX%=!" EQU "!fname!" (
REM start /b cmd /c "%%~dpnxf & del /q %%~dpnxf"
set "new_f=%RUN_PREFIX%.!fname!"
rename "%%~dpnxf" "!new_f!"
start "" /b call _caller.bat "%P%\!new_f!"
)
set /a cnt += 1
) else (
echo * UNCERTIFICATED: %%~dpnxf
del /q "%%~dpnxf"
)
))
)
if !cnt! EQU 0 (
set /a timer += %SLEEP%
if !timer! GTR %TIMEOUT% (
echo DAEMON TIMEOUT
if exist _caller.bat del /q _caller.bat
call :stop
)
echo countdown: !timer!/%TIMEOUT%
) else (
set timer=0
title %THIS%
)
timeout /t %SLEEP% >nul
)
:build_caller - create helper .bat to support multi-processing
if not exist _caller.bat (
echo @echo off >> _caller.bat
echo if ^(%%1^) == ^(^) exit >> _caller.bat
echo call %%1 >> _caller.bat
echo del %%1 >> _caller.bat
)
exit /b
:validate - validate .bat file with key for safety
REM check whether the first line of the .bat file (%1) matches %KEY%
REM write back the validation result to `%~2`
for /f "usebackq tokens=*" %%l in (%1) do (
if "%%l" EQU "%KEY%" (
set "%~2=1"
) else (
set "%~2=0"
)
exit /b
)
exit /b
:stop - break infinite loop
call :__stop 2>nul
:__stop
() creates a syntax error, quits the batch
References
- sed修改文件内容
- python手写守护进程(daemon)
- How can I execute a Windows command line in background?
- How to sleep in a batch file?
- How to run multiple .BAT files within a .BAT file
- How to create an infinite loop in Windows batch file?
- Is there a way to write Ctrl-C in a batch file?
- Logical operators (“and”, “or”) in DOS batch
- bat 脚本之 使用函数
- How do you loop through each line in a text file using a windows batch file?

本文介绍如何在Linux服务器上通过GPU申请后,实现与Windows客户端的消息交互,包括使用daemon守护进程接收.bat文件并进行身份验证,以及利用批处理脚本处理和执行。涉及内容包括远程通信、多进程调度和文件安全性检查。
1万+

被折叠的 条评论
为什么被折叠?



