Open Ubuntu terminal using batch file on windows with command?

I automate many processes on windows using batch files and putty.

E.g ( login_server7.bat ):

start C:\Users\Jack\Documents\putty.exe -ssh 1.1.1.1 -l user123 -pw "bleh"

How am I able to start an Ubuntu terminal and run a command automatically after opening a file?

Rather than manually opening the ubuntu terminal and typing my commands in?

Cannot see anything elsewhere on this topic. Regards


Solution 1:

The executable of WSL is C:\Windows\System32\wsl.exe. You can just type wsl in Windows Command prompt and you will be logged-in to the default WSL instance. Or type wsl -h in order to get the list of all available options. In batch files you can use:

C:\Windows\System32\wsl.exe <your script or command>

Or if you need to run the command as root:

C:\Windows\System32\wsl.exe sudo <your script or command>

Probably more correct way is to use wsl -e -- <command>, but the above works nice for me. Here is more detailed example: Ubuntu 18.04 on WSL cron daemon not running after reboot.

Solution 2:

As ps4080's answer mentions, the right way to do this is wsl -e -- <command> (or, typically wsl -e <command>).

However, there are actually quite a few nuances you might run into with this technique, and it's nice to understand what's going on with each exact incantation so you can use the right one when needed:

wsl <command>

  • Runs the default shell for the current user
  • ... as a non-login, non-interactive shell
  • ... in the directory passed in by the owning Windows process
  • Runs <command> in that shell

Depending on your shell, you can see this with wsl ps -eH:

  PID TTY          TIME CMD
    1 ?        00:00:00 init
   18 ?        00:00:00   init
   19 ?        00:00:00     init
   20 pts/0    00:00:00       fish
   28 pts/0    00:00:00         ps

Note that it's difficult to see this when bash is your default shell since -c results in an implicit exec.

The fact that this runs in the directory of the owning Windows process can be handy, since you can do:

wsl ls -lh

... in PowerShell to get "human readable" file sizes, something that is surprisingly difficult to do otherwise.

The trickiest part of this is that second qualifier. WSL runs your shell as a non-login, non-interactive shell when started this way. This means that ~/.bashrc and ~/.bash_profile are not sourced on startup. This can cause confusion when attempting to run a command that requires something to be done in the startup files (e.g. setting an environment variable).

wsl -e <command>

  • Runs <command> as the shell
  • ... in the directory passed in by the owning process

The -e bypasses your default shell entirely.

> wsl ps -eH
  PID TTY          TIME CMD
    1 ?        00:00:00 init
    7 ?        00:00:00   init
    8 ?        00:00:00     init
    9 pts/0    00:00:00       ps

This can be slightly more efficient since you avoid the startup overhead of the shell, but it's typically not worth worrying about.

wsl -e bash -lic <command>

  • Runs bash as your shell (regardless of whether it is the default shell or not)
  • Forces it to be a login, interactive shell (-li) so that ~/.bashrc and ~/.bash_profile (and/or others) are sourced
  • ... in the directory passed in by the owning Windows process
  • Runs <command> in that shell

This is the version to use if the command needs anything from your startup configuration.