使用 Matlab 将日志语句写入标准输出

发布于 2024-12-09 05:00:49 字数 505 浏览 0 评论 0原文

我们从 Jenkins 构建服务器 启动 Matlab。由于构建可能需要一些时间,因此在 matlab 运行时获得一些日志输出会很好。有没有办法将文本打印到标准输出? disp、fprintf 和 java.lang.System.out.printline 仅写入 matlab 控制台,而不写入标准输出。

使用日志文件 或者管道不会有帮助,因为 Jenkins 仅在构建步骤期间从标准输出读取。

当 matlab 运行时,我们如何将日志语句写入标准输出?

编辑: 我们在 Windows 上运行 Matlab 2010b

We're starting Matlab from our Jenkins buildserver. As the build may take some time it would be nice to get some log-outputs while matlab is running. Is there a way to print text to standard output? disp, fprintf and java.lang.System.out.printline only write to the matlab console, not to standard output.

Using a logfile or a pipe won't help, as Jenkins only reads from standard-output during a build step.

How can we write log-statements to the standard output while matlab is running?

EDIT:
We're running Matlab 2010b on Windows

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

又怨 2024-12-16 05:00:49

根据您使用 Matlab 所做的事情,您可能可以在没有 GUI 的命令行中启动它。我在服务器上使用了它,它的行为非常像 shell 脚本并写入标准输出。

请参阅启动选项

我使用了以下内容:

/path/to/matlab -nojvm -nodisplay -nosplash -nodesktop -r /path/to/mfile

编辑:忘记提及一个非常重要的小细节,在 mfile 末尾放置一个 exit 命令,否则 Matlab 将挂在那里等待。

Depending what you are doing with Matlab you could probably launch it in command line without GUI. I used this on a server and it behaves pretty much like a shell script and writes to standards outputs.

See the startup options.

I used the following:

/path/to/matlab -nojvm -nodisplay -nosplash -nodesktop -r /path/to/mfile

EDIT: forgot to mention one very important little detail, place an exit command at the end of your mfile or Matlab will hang there waiting.

欢你一世 2024-12-16 05:00:49

看来 -wait-log (不是 -logfile 的组合将命令窗口输出克隆到父控制台的标准输出,但如果您调用 [MATLABROOT]\bin 中的 MATLAB 可执行文件,而不是 [MATLABROOT]\bin\win64(当前 arch 的子目录)。

在 Windows R2015b 和 R2016b 上测试:

C:\MATLAB\bin\matlab.exe -wait -log

NOT

C:\MATLAB\win64\bin\matlab.exe -wait -log

如果您使用 -r 运行,请记住在脚本中添加 exit/quit

唯一的麻烦是我似乎找不到 -log 选项的任何文档!嗯。

It seems that the combination of -wait and -log (not -logfile) clones the command window output to the parent console's stdout, but only if you call the MATLAB executable in [MATLABROOT]\bin, not [MATLABROOT]\bin\win64 (the subdirectory for current arch).

Tested on Windows with R2015b and R2016b:

C:\MATLAB\bin\matlab.exe -wait -log

NOT

C:\MATLAB\win64\bin\matlab.exe -wait -log

Remember to put an exit/quit in your script if you are running with -r.

The only trouble is that I can't seem to find any documentation for the -log option! Meh.

耀眼的星火 2024-12-16 05:00:49

在 MATLAB 中似乎没有任何好的方法可以做到这一点。我能想到的最简单的方法是使用 shell 脚本。您可以编写一个小型 shell 脚本,它只需将任何输入打印到 stdout,然后使用 unix (或 system)命令从 matlab 中调用该 shell 脚本。 Jenkins 应该能够读取脚本的命令行输出并使用它。

There don't seem to be any good ways to do this from within MATLAB. The easiest way I can think of doing this is by using a shell script. You could write a small shell script which would simply print any input to stdout, and then call that shell script from within matlab using the unix (or system) commands. Jenkins should be able to read the command-line output of the script and work with that.

橙幽之幻 2024-12-16 05:00:49

我找到了一种方法来做到这一点,并且也在 Windows 上为 Jenkins Matlab 界面做这件事。

基本思想是,您将使用 diary 命令,然后使用 tail -f 文件,但如果您打开多个 matlab 实例,则需要一种聪明的方法来终止 tail 命令,因为会出现名称冲突。因此,我使用的方法是将文件命名为 log.txt,其中使用的 PID 是打开时使用的 MATLAB PID。

MATLAB 中有一个未公开的功能,可以让您获取其 PID。现在,您的批处理文件和 MATLAB 都知道 PID,而无需读取/写入随机文本文件,该文件在执行多个作业时会变得混乱。因此,您可以使用 PID 作为您的唯一标识符。 MATLAB 还使用“tail -f”的 PID 来杀死 tail -f 以使批处理文件失效,并且 MATLAB 使用与进程调用相关的命令行详细信息找到它,因为它再次使用唯一的 PID 日志文件名。

这需要使用一些 wmic 命令并且需要 Windows Vista/7 或更高版本。使用 XP,您可能需要更加努力才能获取进程 ID,但应该仍然是可能的。

要做的事情如下:

1) 获取适用于 Windows 的 gnu awk: http://gnuwin32.sourceforge.net /packages/gawk.htm

2) 从 Windows 资源工具包中获取 tail.exe:http://www.microsoft.com/en-us/download/details .aspx?id=17657

3) 确保 tail 和 awk 位于您的路径中(我认为 Windows 资源工具包不会自动将它们放入路径中)

3) 创建一个名为 matlabrun.bat 的批处理文件,如下所示如下,(注意:您需要关闭@echo,而且整个命令很长,向右滚动..)

@echo off
wmic process call create "c:\matlab\bin\win64\matlab.exe -r \"cd('c:\jenkins\workspace\test'); workdir=pwd; outpath=[pwd '\output'] ; try; run('C:\MATLAB\work\test_run'); end; quit; \" "  | findstr ProcessId | awk "{print $3}" | awk -F";" "{ print $1 }"

4)创建另一个名为 run.bat 的批处理文件:

for /f %%i in ('matlabrun.bat') do (

 echo MATLAB Log... > log%%i.txt

 tail -f log%%i.txt

 set logfilename=log%%i.txt

 goto next

)

:next

del /f %logfilename%

5)run.bat 文件将执行 matlabrun.bat 并由于 -wait 没有传递,matlab 会立即返回命令行并执行 tail -f 命令。这将阻止批处理文件完成,直到您终止它。 matlabrun.bat 返回 matlab 的 PID。

6) 另一个重要注意事项:由于您使用的是“wmic process create”,它将为您提供 MATLAB 正在使用的 PID,但默认工作目录为 c:\windows\system32。这就是为什么我将工作目录传递给 matlab。 wmic process create 对于将哪些参数放入命令字符串中以便让 matlab 运行也有一点特殊。因此,在命令字符串中使用逗号似乎存在问题。所以我建议不要使用它们,或者弄清楚如何转义它们(可能是 ^, 有效,但我只是在 matlab run 命令中删除了逗号)。

6) “test_run.m”文件包含以下代码,用于写入正确的日志文件并终止正确的 tail -f 实例。

matlabpid=feature('getpid');
filename=['log',num2str(matlabpid),'.txt'];
filenamefull=[workdir,'\',filename];

diary(filenamefull);
disp('Script starting...')


%%% put your code here %%%


disp('Script completed...');
diary off;

%%% FIND PID of tail.exe and kill it 
%%% by using the name of the log file in the process command line
[a,b]=dos(['wmic process get Commandline,ProcessId']);
C=textscan(b,'%s','delimiter','\n');C=C{1};
for jj=1:size(C,1),
    if strfind(C{jj},filename),
        D=textscan(C{jj},'%s');D=D{1};
        dos(['taskkill /f /pid ',D{4}]) %kills tail.exe which is the log watcher
        break
    end
end

7) 通过执行 run.bat 来启动它。它将执行 matlab,然后在 MATLAB 实时运行时开始跟踪输出。然后完成后它将删除日志文件。

8)我的目录结构/文件位于这些位置(我使用的是win7 64位):

c:\jenkins\workspace\test\tail.exe

c:\jenkins\workspace\test\awk.exe

c:\jenkins\workspace \test\matlabrun.bat

c:\jenkins\workspace\test\run.bat

c:\matlab\work\test_run.m

c:\matlab\bin\win64\matlab.exe

如果您使用的是 32 位 matlab,请将其指向 win32 目录。要获得正确的 PID,您需要在 win32 或 win64 目录中指定实际的 matlab.exe 二进制文件。

I figured out a way to do this and am also doing it for Jenkins Matlab interface on windows.

Basic idea is that you will use diary command, but then tail -f the file, but you need a smart way to kill the tail command if you open multiple matlab instances because there will be name collisions. So the method I'm using is to name the file log.txt where the PID used is MATLAB's PID it is using when it opens.

There is an undocumented feature in MATLAB that allows you to get its PID. So now, both your batch file and MATLAB know the PID without having to read/write to a random text file that will get messy when executing multiple jobs. So the PID you use that as your unique identifier. The PID of "tail -f" is also used by MATLAB to kill tail -f to make the batch file die and is found by MATLAB using the commandline details associated with the process invocation since it uses again the unique PID log file name.

This uses some wmic commands and needs Windows Vista/7 or above. With XP you probably have to work harder to get the process ID's but should be still possible.

Here is what to do:

1) Get gnu awk for windows: http://gnuwin32.sourceforge.net/packages/gawk.htm

2) Get tail.exe from windows resource kit: http://www.microsoft.com/en-us/download/details.aspx?id=17657

3) Make sure tail and awk are in your path (the windows resourece kit I don't think automatically puts them in the path)

3) Create a batch file called matlabrun.bat as follows, (note: you need the @echo off, also the entire command is quite long, scroll right..)

@echo off
wmic process call create "c:\matlab\bin\win64\matlab.exe -r \"cd('c:\jenkins\workspace\test'); workdir=pwd; outpath=[pwd '\output'] ; try; run('C:\MATLAB\work\test_run'); end; quit; \" "  | findstr ProcessId | awk "{print $3}" | awk -F";" "{ print $1 }"

4) Create another batch file called run.bat with:

for /f %%i in ('matlabrun.bat') do (

 echo MATLAB Log... > log%%i.txt

 tail -f log%%i.txt

 set logfilename=log%%i.txt

 goto next

)

:next

del /f %logfilename%

5) The run.bat file will execute matlabrun.bat and since -wait is not passed, matlab will immediately return to the command line and execute the tail -f command. That will block the batch file from completing until you kill it. matlabrun.bat returns the PID of matlab.

6) Another important note: since you are using "wmic process create" which will provide you with a PID that MATLAB is using, but will default to a working directory of c:\windows\system32. So that is why I pass the work directory to matlab. wmic process create is also a bit particular about what parameters you put into your command string for matlab to run. So it appears to have a problem with using commas in your command string. So I suggest not to use those, or figure out how to escape them (it might be that ^, works, but I just removed my commas anyway in my matlab run command).

6) The "test_run.m" file contains the following code to write to the correct log file and to kill correct tail -f instance.

matlabpid=feature('getpid');
filename=['log',num2str(matlabpid),'.txt'];
filenamefull=[workdir,'\',filename];

diary(filenamefull);
disp('Script starting...')


%%% put your code here %%%


disp('Script completed...');
diary off;

%%% FIND PID of tail.exe and kill it 
%%% by using the name of the log file in the process command line
[a,b]=dos(['wmic process get Commandline,ProcessId']);
C=textscan(b,'%s','delimiter','\n');C=C{1};
for jj=1:size(C,1),
    if strfind(C{jj},filename),
        D=textscan(C{jj},'%s');D=D{1};
        dos(['taskkill /f /pid ',D{4}]) %kills tail.exe which is the log watcher
        break
    end
end

7) You start it by doing run.bat. It will go and execute matlab, then start tailing the output while MATLAB runs in real-time. Then when done it will delete the log file.

8) My directory structure / files are in these locations (I'm using win7 64bit):

c:\jenkins\workspace\test\tail.exe

c:\jenkins\workspace\test\awk.exe

c:\jenkins\workspace\test\matlabrun.bat

c:\jenkins\workspace\test\run.bat

c:\matlab\work\test_run.m

c:\matlab\bin\win64\matlab.exe

If you are using 32bit matlab, point it to the win32 directory. To get the correct PID, you need to specify the actualy matlab.exe binary in the win32 or win64 directory.

迷荒 2024-12-16 05:00:49

您可以通过将 -logfile 选项指向 Jenkins 日志文件来完成此操作。像下面这样:

"C:\path\to\matlab.exe" "-r" "functionToRun" "-logfile" "%JENKINS_HOME%\jobs\%JOB_NAME%\builds\%BUILD_NUMBER%\log" /wait

You can do this by pointing the -logfile option to the Jenkins log file. Something like the following:

"C:\path\to\matlab.exe" "-r" "functionToRun" "-logfile" "%JENKINS_HOME%\jobs\%JOB_NAME%\builds\%BUILD_NUMBER%\log" /wait
謌踐踏愛綪 2024-12-16 05:00:49

您可以使用日记模式。不确定它是否适合您的具体实施。

http://www.mathworks.com/help/techdoc/ref/diary.html

You can use the diary mode. Not sure if it will fit your specific implementation.

http://www.mathworks.com/help/techdoc/ref/diary.html

桃扇骨 2024-12-16 05:00:49

我没有找到真正的解决方案。 Mathworks 创建了一些包装工具。但这只会在matlab退出后输出结果。执行期间您不会得到任何输出。

http:// /www.mathworks.de/support/solutions/en/data/1-ACT3YN/index.html?product=ML&solution=1-ACT3YN

所以我将没有真实的现场输出...

I didn't find a real solution. Mathworks created some wrapper tool. But this will only output the results after matlab has exited. You won't get any ouput during execution.

http://www.mathworks.de/support/solutions/en/data/1-ACT3YN/index.html?product=ML&solution=1-ACT3YN

So I'll have live without real live-output...

无可置疑 2024-12-16 05:00:49

或者尝试在 matlab 中使用“-logfile”选项。

matlab.exe -nodisplay -nosplash -nodesktop -wait -logfile logfile.txt -r "try script.m ;catch err; disp(err.message); end ; exit"

我更喜欢在 Jenkins 中使用 bash(执行 shell),然后您可以在 matlab 运行时跟踪日志文件。

matlab.exe <...> &
matpid=$!
tail -f logfile.txt &
tailpid=$!
wait $matpid
matexit=$?
kill $tailpid
sleep 1 # Just to make sure kill is done before Jenkins step ends and no zombie processes
exit $matexit

Or try using '-logfile' option in matlab.

matlab.exe -nodisplay -nosplash -nodesktop -wait -logfile logfile.txt -r "try script.m ;catch err; disp(err.message); end ; exit"

I prefer using bash (Execute shell) in Jenkins, then you can tail the log-file while matlab is running.

matlab.exe <...> &
matpid=$!
tail -f logfile.txt &
tailpid=$!
wait $matpid
matexit=$?
kill $tailpid
sleep 1 # Just to make sure kill is done before Jenkins step ends and no zombie processes
exit $matexit
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文