1

I am trying to launch a steam game on my computer through an ssh connection (into a Win10 machine). When run locally, the following python call works.

subprocess.run("start steam://rungameid/[gameid]", shell=True)

However, whenever I run this over an ssh connection—either in an interactive interpreter or by invoking a script on the target machine—my steam client suddenly exits.

I haven't noticed anything in the steam logs except that Steam\logs\connection_log.txt contains logoff and a new session start each time. This is not the case when I run the command locally on my machine. Why is steam aware of the different sources of this command, and why is this causing the steam connection to drop? Can anyone suggest a workaround?

Thanks.

Dan
  • 147
  • 14
  • 2
    how are you ssh into the windows machine? – Joran Beasley Jun 09 '21 at 23:55
  • I'm running OpenSSH SSH Server and Authentication Agent on the windows machine and sshing into [windows_account]@[fixed_ip] from an android phone on the local wireless running JuiceSSH. – Dan Jun 10 '21 at 00:42
  • It may want whatever the equivalent of the X DISPLAY variable is under Windows - does this happen if you create a script with similar contents and run _that_ under ssh? – ti7 Jun 14 '21 at 15:54
  • 1
    I think you are encountering the same problem as in [this question](https://stackoverflow.com/questions/59880794/starting-gui-programs-via-openssh-on-windows). (See [this answer](https://stackoverflow.com/a/65899949) by [domih](https://stackoverflow.com/users/1037303/domih) for an explanation.) In short, you could [download](https://github.com/PowerShell/Win32-OpenSSH/releases) and run OpenSSH server manually instead of using the OpenSSH Windows service. I was able to launch Steam apps over SSH that way. – fakedad Jun 15 '21 at 13:31
  • @fakedad that was exactly the issue. Thanks so much! If you want to put your response in an answer, I'll go ahead and accept it. – Dan Jun 17 '21 at 18:27

1 Answers1

1

Steam is likely failing to launch the application because Windows services, including OpenSSH server, cannot access the desktop, and, hence, cannot launch GUI applications. Presumably, Steam does not expect to run an application in an environment in which it cannot interact with the desktop, and this is what eventually causes Steam to crash. (Admittedly, this is just a guess—it's hard to be sure exactly what is happening when the crash does not seem to appear in the logs or crash dumps.)

You can see a somewhat more detailed explanation of why starting GUI applications over SSH fails when the server is run as a Windows service in this answer by domih to this question about running GUI applications over SSH on Windows.

domih also suggests some workarounds. If it is an option for you, the simplest one is probably to download and run OpenSSH server manually instead of running the server as a service. You can find the latest release of Win32-OpenSSH/Windows for OpenSSH here.


The other workaround that still seems to work is to use schtasks. The idea is to create a scheduled task that runs your command—the Task Scheduler can access the desktop. Unfortunately, this is only an acceptable solution if you don't mind waiting until the next minute at least; schtasks can only schedule tasks to occur exactly on the minute. Moreover, to be safe to run at any time, code should probably schedule the task for at least one minute into the future, meaning that wait times could be anywhere between 1–2 minutes.

There are also other drawbacks to this approach. For example, it's probably harder to monitor the running process this way. However, it might be an acceptable solution in some circumstances, so I've written some Python code that can be used to run a program with schtasks, along with an example. The code depends on the the shortuuid package; you will need to install it before trying the example.

import subprocess
import tempfile
import shortuuid
import datetime

def run_with_schtasks_soon(s, delay=2):
    """
    Run a program with schtasks with a delay of no more than
    delay minutes and no less than delay - 1 minutes.
    """
    # delay needs to be no less than 2 since, at best, we
    # could be calling subprocess at the end of the minute.
    assert delay >= 2
    task_name = shortuuid.uuid()
    temp_file = tempfile.NamedTemporaryFile(mode="w", suffix=".bat", delete=False)
    temp_file.write('{}\nschtasks /delete /tn {} /f\ndel "{}"'.format(s, task_name, temp_file.name))
    temp_file.close()
    run_time = datetime.datetime.now() + datetime.timedelta(minutes=delay)
    time_string = run_time.strftime("%H:%M")
    # This is locale-specific. You will need to change this to
    # match your locale. (locale.setlocale and the "%x" format
    # does not seem to work here)
    date_string = run_time.strftime("%m/%d/%Y")
    return subprocess.run("schtasks /create /tn {} /tr {} /sc once /st {} /sd {}".format(task_name,
                                                                                         temp_file.name,
                                                                                         time_string,
                                                                                         date_string),
                          shell=True)
                          
if __name__ == "__main__":
    # Runs The Witness (if you have it)
    run_with_schtasks_soon("start steam://rungameid/210970")
fakedad
  • 1,292
  • 1
  • 10
  • 21
  • I succeeded in addressing the problem using the first solution, running the ssh server directly instead of as a service. The alternative approach, however, is also interesting. I'll have to consider whether the time delay would matter significantly for my use case. Thanks! – Dan Jun 19 '21 at 00:24