【问题标题】:WSL run linux from windows without spawning a cmd-windowWSL 从 Windows 运行 linux 而不产生 cmd 窗口
【发布时间】:2017-05-04 16:32:14
【问题描述】:

我在 cmd 中运行 WSL bash。我不会将它用于任何事情,它只是挂在那里以保持 WSL 系统的活力。

当我启动 X 应用程序时:

bash -c "DISPLAY=:0 xmessage hello &"

我得到这个结果:

我可以毫无问题地关闭命令窗口,但这很烦人。

如何运行命令而不每次都得到这个cmd窗口?

【问题讨论】:

    标签: windows bash ubuntu windows-subsystem-for-linux


    【解决方案1】:

    所以我现在只是做了这个解决方法。我真的希望有比这更好的方法,但它就是这样:

    在纯粹为了保持 WSL 活着而存在的命令提示符中,我运行了这个脚本:

    wsl_run_server

    #!/bin/bash
    set -e
    nc -kl 127.0.0.1 15150 | sh
    

    然后我有这个命令在后台执行命令:

    wsl_run_command

    if ! pidof -x bin/wsl_run_server; then
        echo wsl_run_server isnt running!
        exit 1
    fi
    echo \($@\) \& | nc localhost 15150
    

    然后我从窗口调用:

    bash -c "DISPLAY=:0 ~/bin/wsl_run_command xmessage hello"
    

    【讨论】:

    • 在你上面的例子中,这应该是 wsl_run_background_command 而不是 wsl_run_command xmessage?
    【解决方案2】:

    这是一个更简单的解决方案,但是,它需要基于WSH 的帮助脚本runHidden.vbs(见底部):

    wscript .\runHidden.vbs bash -c "DISPLAY=:0 xmessage 'hello, world'"
    

    应用@davv 自己的后台启动技术来避免每次都创建一个新的bash 实例:

    一次性操作(例如,在启动时):启动一个隐藏的、保持打开的bash 窗口。这会产生 2 bash 进程:Windows bash.exe 进程拥有控制台窗口,以及 WSL bash 进程(由 WSL init 单例拥有),然后可用于服务后台命令

    wscript .\runHidden.vbs bash # hidden helper instance for servicing background commands
    

    对于每个 X Window 启动命令:使用 & 终止每个命令,使其由隐藏的 WSL bash 实例运行异步,不让 invoking bash 实例保持活动状态:

    wscript .\runHidden.vbs bash -c "DISPLAY=:0 xmessage 'hello, world' &"
    

    runHidden.vbs源码:

    ' Simple command-line help.
    select case WScript.Arguments(0)
    case "-?", "/?", "-h", "--help"
      WScript.echo "Usage: runHidden executable [...]" & vbNewLine & vbNewLine & "Runs the specified command hidden (without a visible window)."
      WScript.Quit(0)
    end select
    
    ' Separate the arguments into the executable name
    ' and a single string containing all arguments.
    exe = WScript.Arguments(0)
    sep = ""
    for i = 1 to WScript.Arguments.Count -1
      ' Enclose arguments in "..." to preserve their original partitioning.
      args = args & sep & """" & WScript.Arguments(i) & """"
      sep = " "
    next
    
    ' Execute the command with its window *hidden* (0)
    WScript.CreateObject("Shell.Application").ShellExecute exe, args, "", "open", 0
    

    即使从 GUI 应用程序启动(例如通过使用 Win+R 调用的Run 对话框),也不会显示控制台窗口。

    如果您的系统默认配置为使用wscript.exe 执行.vbs 脚本(我认为wscript //h:wscript /s 是默认配置),您可以调用@ 987654341@ 直接,如果你把它放在你的%PATH% 中,仅按文件名(根):runHidden ...

    请注意,该脚本的使用不仅限于控制台应用程序:即使是 GUI 应用程序也可以使用它隐藏运行。

    【讨论】:

      【解决方案3】:

      还有另一个简单的解决方案,不过它需要一个外部可执行文件。它没有依赖,被aseering on GitHub推荐。

      您可以通过 run.exe 启动 bash:run.exe bash.exe -c ""。 (run.exe在这里:http://www.straightrunning.com/projectrun/,请确保您下载的是64位版本,32位版本将无法找到或运行bash)。

      在搜索路径上使用run,您只需调用

      run bash -c "DISPLAY=:0 xmessage hello"

      【讨论】:

      • 对于这个,run.exe 抱怨找不到 bash 或 bash.exe。顺便说一句,bash.exe 和 run.exe 在同一个 ...\system32 目录中。有什么想法吗?
      • 可能您需要 64 位版本的 run.exe(Sjoerd van Leent 建议编辑)。
      【解决方案4】:

      运行命令后台

      screen -dmS [name] [command]

      示例

      screen -dmS gui bash -c "DISPLAY=:0 xmessage hello"

      在windows桌面上创建快捷方式(在wsl中运行)

      wslusc screen -dmS gui bash -c "DISPLAY=:0 xmessage hello"

      【讨论】:

        【解决方案5】:

        最近添加了 WSLg 后,不再需要弹出该命令窗口。您可以使用 WSLg 调用 bash,就像这样(我目前在 WSL 中使用 Ubuntu):

        wslg ~ -d Ubuntu bash

        这将创建一个 BASH 会话,该会话将坐在那里而不会被看到。或者,您可以像我一样运行一些保持运行的服务。我创建了一个脚本来检查正在运行的服务,如果它没有发现它们正在运行,将运行它们。在 /usr/bin 中创建文件:

        sudo touch /usr/bin/start-wsl-services

        sudo nano /usr/bin/start-wsl-services

        将以下内容粘贴到文件中:

        #!/bin/bash
        
        # Check for and run System-wide DBus service.
        SERVICE="dbus-daemon"
        if pgrep -x "$SERVICE" >/dev/null
        then
            pgrep -a "$SERVICE"
        else
            sudo /etc/init.d/dbus start
            pgrep -a "$SERVICE"
        fi
        
        # Check for and run CUPS Printing Service.
        SERVICE="cupsd"
        if pgrep -x "$SERVICE" >/dev/null
        then
            pgrep -a "$SERVICE"
        else
            sudo /etc/init.d/cups start
            pgrep -a "$SERVICE"
        fi
        
        # Check for and start Freshclam CLAMAV Update service.
        SERVICE="freshclam"
        if pgrep -x "$SERVICE" >/dev/null
        then
            pgrep -a "$SERVICE"
        else
            sudo /etc/init.d/clamav-freshclam start
            pgrep -a "$SERVICE"
        fi
        
        # Check for and start SANED Scanner service.
        SERVICE="saned"
        if pgrep -x "$SERVICE" >/dev/null
        then
            pgrep -a "$SERVICE"
        else
            sudo /etc/init.d/saned start
            pgrep -a "$SERVICE"
        fi
        
        # Check for and start screen-cleanup service.
        SERVICE="screen-cleanup"
        if pgrep -x "$SERVICE" >/dev/null
        then
            pgrep -a "$SERVICE"
        else
            sudo /etc/init.d/screen-cleanup start
            pgrep -a "$SERVICE"
        fi
        
        # Check for and start Preload service.
        SERVICE="preload"
        if pgrep -x "$SERVICE" >/dev/null
        then
            pgrep -a "$SERVICE"
        else
            sudo /etc/init.d/preload start
            pgrep -a "$SERVICE"
        fi
        
        # Prestart LibreOffice twice for faster loading.
        #/usr/bin/libreoffice --terminate_after_init
        #sleep 5
        #/usr/bin/libreoffice --terminate_after_init
        
        # Check for error, make sure all functions called and run, and pass the result on to calling process.
        if [[ $? -ne 0 ]] ; then
            exit 1
        else
            exit 0
        fi
        

        保存并退出文件,然后使其可执行:

        sudo chmod +x /usr/bin/start-wsl-services

        然后我使用在启动时运行启动脚本的快捷方式调用它。或者您可以手动运行它。我在启动脚本中使用的命令是:

        C:\Windows\System32\wslg.exe -d Ubuntu -- /usr/bin/start-wsl-services

        我使用的启动命令脚本(命名为StartWSL.cmd)如下:

        @echo off
        
        echo Starting WSL Linux...
        
        :RETRY
        
        C:\Windows\System32\wslg.exe -d Ubuntu -- /usr/bin/start-wsl-services
        
        REM - C:\Windows\System32\bash.exe -c '/usr/bin/start-wsl-services'
        
        IF %ERRORLEVEL% NEQ 0 (GOTO RETRY)
        
        REM - Allow time to see all results.
        timeout /t 5 /nobreak >NUL
        
        REM - Uncomment below line for troubleshooting.
        REM - pause
        
        exit 0
        

        这就是我现在在 Windows 11 上保持 WSL 在后台运行的方式,类似于我在 Windows 10 上的方式。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-27
          • 1970-01-01
          • 2022-01-18
          • 2021-04-17
          • 2021-12-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多