Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix 在Oracle Solaris 11上关闭控制台并打开新控制台后,将.jar应用程序输出流抓取到控制台_Unix_Console_Solaris - Fatal编程技术网

Unix 在Oracle Solaris 11上关闭控制台并打开新控制台后,将.jar应用程序输出流抓取到控制台

Unix 在Oracle Solaris 11上关闭控制台并打开新控制台后,将.jar应用程序输出流抓取到控制台,unix,console,solaris,Unix,Console,Solaris,在Oracle Solaris 11控制台上,当发出ps-ef | grep java命令时,我可以看到正在运行一些java进程PID,该进程PID在其他控制台窗口上启动,然后它(控制台窗口)关闭(.jar应用程序输出可见)。是否可以在不重新启动.jar文件的情况下再次获取应用程序输出 应用程序是这样启动的(作为root用户): 在这种情况下,将输出写入文件不是一个选项。是的,您可以这样做,但它涉及到一些使用gdb的疯狂技能。下面是在Linux中如何做到这一点,我相信在Solaris中也可以做到

在Oracle Solaris 11控制台上,当发出
ps-ef | grep java
命令时,我可以看到正在运行一些java进程PID,该进程PID在其他控制台窗口上启动,然后它(控制台窗口)关闭(.jar应用程序输出可见)。是否可以在不重新启动.jar文件的情况下再次获取应用程序输出

应用程序是这样启动的(作为
root
用户):


在这种情况下,将输出写入文件不是一个选项。

是的,您可以这样做,但它涉及到一些使用gdb的疯狂技能。下面是在Linux中如何做到这一点,我相信在Solaris中也可以做到这一点(因为它有gdb,并且它有我将进一步使用的所有需要的系统调用)

标准流有3个文件描述符:

  • 标准偏差:0
  • 标准:1
  • 标准:2
您对stdout和stderr(两者都是控制台输出)感兴趣,因此需要编号为12的文件描述符,请记住这一点

现在,我将向您展示如何为stderr流执行“okular”应用程序(而不是“java”应用程序)所要求的操作

  • 在终端中运行“Okula”,如下所示:

    $ okular &
    
    然后关闭这个终端。这只是为了模拟你的情况

  • 打开另一个终端
  • 寻找“okular”流程:

    输出:

    joe      27599  2.2  0.9 515644 73944 ?        S    23:46   0:00 okular
    
    lrwx------ 1 joe joe 64 Feb 18 23:46 0 -> /dev/pts/0 (deleted)
    lrwx------ 1 joe joe 64 Feb 18 23:46 1 -> /dev/pts/0 (deleted)
    lrwx------ 1 joe joe 64 Feb 18 23:46 2 -> /dev/pts/0 (deleted)
    
    所以“okular”PID是27599

  • 查找“okular”进程的打开文件描述符:

    输出:

    joe      27599  2.2  0.9 515644 73944 ?        S    23:46   0:00 okular
    
    lrwx------ 1 joe joe 64 Feb 18 23:46 0 -> /dev/pts/0 (deleted)
    lrwx------ 1 joe joe 64 Feb 18 23:46 1 -> /dev/pts/0 (deleted)
    lrwx------ 1 joe joe 64 Feb 18 23:46 2 -> /dev/pts/0 (deleted)
    
    您会看到所有3个流都被删除

  • 现在,让我们用gdb连接到我们的流程:

    $ gdb -p 27599 /usr/bin/okular
    
    在gdb内部执行下一步操作:

    (gdb) p close(2)
    (gdb) p creat("/tmp/okular_2", 0600)
    (gdb) detach
    (gdb) quit
    
    这里我们调用了两个系统调用:

    • close(),关闭进程流的stderr文件
    • create(),为流程的stderr流创建新文件
    p是gdb命令,它打印(在本例中)系统调用返回值

  • 现在,我们流程的所有新的stderr输出将被附加到文本文件/tmp/okula_2。我们可以这样不断地阅读:

    $ tail -f /tmp/okular_2
    
  • 结论 好了,就这样,我们恢复了stream。您可以对stdout流执行相同的操作,唯一的区别是您需要在gdb中调用“close(1)”而不是“close(2)”。此外,在您的情况下,请确保将所有“okular”单词替换为“java”单词

    大部分答案都是受到了启发


    如果需要恢复stdin流,可以将其附加到管道(FIFO)文件,请参阅详细信息。

    是的,可以使用Solaris本机工具监视任何进程输出

    一种方法是使用
    dtrace
    ,它允许跟踪进程,即使它们已经被调试器或类似工具捕获

    dtrace
    脚本将显示给定的进程
    stdout

    #!/bin/ksh
    pid=$1
    dtrace -qn "syscall::write:entry /pid == $pid && arg0 == 1 /
      { printf(\"%s\",copyinstr(arg1)); }"
    
    您应该将java应用程序的进程id作为其第一个参数传递给trace,例如,
    $(pgrep-f“java-jar SomeFile.jar”)

    如果要跟踪
    stderr
    vs
    stdin
    ,请将
    arg0==1
    替换为
    arg0==2

    如果要查看不可显示的字符(八进制),可以使用此稍加修改的版本:

    #!/bin/ksh
    pid=$1
    dtrace -qn "syscall::write:entry /pid == $pid && arg0 == 1 /
      { printf(\"%s\",copyinstr(arg1)); }" | od -c
    
    另一种本地方法是使用
    truss
    命令。以下脚本将显示从进程到任何文件描述符的所有写入,并将包括
    stdout
    stderr
    的完整详细跟踪(3799是您的目标进程pid):


    dtrace:

    桁架:

    试图在Solaris11上查找
    gdm
    。我想我需要先安装这个软件包。只有它是gdb,不是gdm:)是的,你可以从这里安装它(对于Solaris):。或者您可以手动生成它:。实际上,您可以使用任何调试器,而不仅仅是gdb。只需确保它能够连接到进程并执行系统调用。语法可能会有所不同,所以我建议您使用gdb,因为我已经测试了我提供的过程(使用gdb),它可以工作。我尝试过这样:
    gdb-p 3228 someApp.jar
    ,但在一些结果中,我发现这行代码:
    “someApp.jar”:不是可执行格式:无法识别的文件格式。。很奇怪,你可以用“gdb-P3228”。如果您想向gdb(用于符号)提供可执行二进制文件,那么应该提供“java”可执行文件的路径,而不是jar文件的路径。好的,现在我得到了以下输出:
    附加到进程3228 Retry#1:Retry#2:Retry#3:Retry#4:[New lwp1]0xff27bf0a in??()(gdb)
    。似乎不是很有用的信息。。(总共8行-很难在注释中格式化:)当然-PID 3228只是一个例子。我得到了这个错误:
    dtrace:invalid probe specifier syscall::write:entry/3799==&&arg0==1/{printf(%s,copyinstr(arg1));}:靠近“&&&&”
    对不起,我不清楚。此脚本期望一个名为pid的shell变量包含要跟踪的程序的进程id。还有一个问题是双引号。用经过测试的方式编辑回复。是的,它工作正常,但我看到文本输出中有很多错误。看起来像终端窗口中的白色方块…是什么让您断言这些是错误?这些方块可能只是JVM或终端仿真器无法表示的非ASCII字符。您可以通过管道将脚本输出到
    od-c
    ,以查看它们的八进制值。回复再次更新,以另一种方式更新,这也将有助于确定这些字符的确切含义。您有什么理由不跟进目前提供的回复?
    #!/bin/ksh
    pid=$1
    dtrace -qn "syscall::write:entry /pid == $pid && arg0 == 1 /
      { printf(\"%s\",copyinstr(arg1)); }" | od -c
    
    truss -w1,2 -t write -p 3799