Linux to windows execute commands remotely - windows

I have to zip files on a remote windows machine.
So I first ssh to the windows machine
ssh my_user#my_host "cd /d D:\MyFolder"
And the above command works.
However if I try to run any command after that it fails.
So if I do something like
ssh my_user#my_host "cd /d D:\MyFolder; dir"
The system cannot find the path specified.

You can try something like:
ssh my_user#my_host <<EOF
cd /d D:\MyFolder
dir
EOF
The second EOF should be alone on the line and start from the begin

Related

Execute a command (TortoiseHG) through cmd remotely (PsExec)

Basically I want to use PsExec in order to navigate to a specificar folder in a remote computer and performe "hg update branch". I've tried to create the following batch but I'm not able to perform the command:
psexec cmd.exe /c "cd C:\Project\hg update Test"
It's reading as the "hg update Test" was a folder instead of command to be done... I'm tilting over here and this seems like a basic thing :(. How do I pass the "hg update branch" as cmd command through PsExec?
You don't need to change directory, just tell HG what path to operate in:
psexec cmd.exe /c "hg update -R C:\Project\ Test"
The help says:
-R --repository REPO repository root directory ...

Excute sh script using git-bash on Windows 10 using ssh

I want to execute an sh script on a remote Windows 10 computer without logging into interactive shell.
On Linux I would do something like
ssh user#machine "echo execute program automatically && ./my_program "
However when I ssh into my Windows 10 machine using open-ssh server it opens by default cmd. In interactive mode I would now open git-bash
"C:\Program Files\Git\bin\sh.exe" --login
Then execute my script from there.
When I try to combine the commands like this
ssh user#machine ' "C:\Program Files\Git\bin\sh.exe" --login && ./my_program " '
the shell freezes. Without the single quotes, the command also doesn't work (obviously).
So what to do?
Try to change default shell, with administrator CMD :
reg add HKLM\SOFTWARE\OpenSSH /v DefaultShell /d "C:\Program Files\Git\bin\sh.exe"

Shutdown or Reboot a WSL session from inside the WSL session

I would like to be able to reboot WSL sessions. To do so is a little awkward as WSL does not use systemd so we cannot use reboot. Within a WSL session, we can run any Windows executable:
boss#Asus: ~ $ wsl.exe -l -v
NAME STATE VERSION
* Ubuntu-20.04 Running 2
fedoraremix Stopped 1
Alpine Stopped 1
Ubuntu Stopped 1
Therefore, we can use wsl.exe (you have to make sure to always add .exe when calling Windows commands or they will not work) to shutdown the currently running WSL session wsl.exe -t Ubuntu-20.03, but the problem is that I don't know the session name.
When we are inside a WSL session, hostname is something different, and so I don't know how to find the name of the currently running session that I am inside (maybe a Windows process command that tells me what process I am running from??).
Ideally, I would like a command to equate to a reboot. I guess this would have to look something like:
Run an asynchronous command that will initiate a new session 5-10 seconds in the future to allow the previous session to fully shutdown (and that will not terminate when this session is terminated).
Terminate the currently running session with wsl.exe -t <my found name>.
A few seconds later, the new session will start up.
Credits to the commenters above.
To shutdown a session from within a WSL guest, you can run:
wsl.exe --terminate $WSL_DISTRO_NAME
Rebooting is also possible, however so far I do not know how to get a new terminal inside the same console window. The following will reboot the WSL guest and open a new console window of it when it has finished:
cd /mnt/c/ && cmd.exe /c start "rebooting WSL" cmd /c "timeout 5 && wsl -d $WSL_DISTRO_NAME" && wsl.exe --terminate $WSL_DISTRO_NAME
Explanation:
From the perspective of Windows, WSL systems are mounted as network resources. cmd does not support the resulting UNC path formats such as \\wsl$\Debian\<...>. Therefore it may be best to cd to a directory it can resolve as a Windows path instead, such as C:\, before it is executed. If ommited, cmd will complain and change its directory to cmd's %windir%.
&& runs another command after the previous one has finished in linux and windows cmd.
cmd.exe /c starts a cmd instance and tells it to execute a command that follows.
start "<WindowTitle>" ... is a cmd-internal command to run another program inside its own window, independent of the cmd instance. In this case the program is another cmd window. It will not be affected when WSL shuts down.
In the original Linux-Terminal, the first cmd /c command has finished, and the third command after && shuts down the guest like above.
The second cmd window waits for a few seconds, then starts a new WSL session of the same WSL machine.
Creating an Alias
You can make this easier to use by creating an alias. For bash users, edit your ~/.bashrc file and apply the changes afterwards:
nano ~/.bashrc && source ~/.bashrc
Add either or both of the lines below anywhere in the file.
You can of course choose any name you want. Both shutdown and reboot exist as systemd commands, but since they do not work in WSL machines, you can replace them with an alias as follows:
alias shutdown='wsl.exe --terminate $WSL_DISTRO_NAME'
alias reboot='cd /mnt/c/ && cmd.exe /c start "rebooting WSL" cmd /c "timeout 5 && wsl -d $WSL_DISTRO_NAME" && wsl.exe --terminate $WSL_DISTRO_NAME'
Expanding on the ansver from #BasementScience
To manage a remote WSL I've set up a Windows TaskScheduler job to start wsl with an /etc/init-wsl which in turn starts cron, ssh, rsyslog and autossh (so I can connect back to WSL).
So naturally I'm keen to get these processes started also on a remote WSL reboot, so I'm able to login again afterwards.
# Added to $HOME/.bashrc - Renamed aliases to separate from OS commands
alias wslshutdown='wsl.exe --terminate $WSL_DISTRO_NAME'
alias wslreboot='cd /mnt/c/ && cmd.exe /c start "Rebooting WSL" cmd /c "timeout 5 && wsl -d $WSL_DISTRO_NAME" -- sudo /etc/init-wsl && wsl.exe --terminate $WSL_DISTRO_NAME'
The detail is here ... & wsl -d $WSL_DISTRO_NAME" -- sudo /etc/init-wsl & ...
This will not start a new shell, but will start my processes so I can login again.
The /etc/init-wsl script have to be created:
sudo touch /etc/init-wsl && sudo chmod 755 /etc/init-wsl
# Add services as needed
sudo bash -c 'cat << EOF > /etc/init-wsl
service ssh start
service cron start
EOF'
# Ensure your user (the %sudo group) can sudo the init script without password
sudo bash -c 'cat << EOF > /etc/sudoers.d/user-service
%sudo ALL=NOPASSWD: /usr/sbin/service *
%sudo ALL=NOPASSWD: /etc/init-wsl
EOF'

Running part of bash script on a remote machine

I need to run some commands locally and then some command on a remote machine all using a single local bash script.
For simplicity just say I want to do the following and execute it on my local desktop machine.
#!/bin/bash
#upload some files to a remote machine
cd /tmp
./upload-files.sh
#run commands on remote machine
ssh myuser:mypass#somewhere.com
cd /tmp/uploads <--- these commands don't run in the ssh connection
./process-uploads.sh
exit
#run command locally again.
cd -
echo 'complete!'
Any ideas of how to do this?
You can use here-doc with ssh command:
#!/bin/bash
#upload some files to a remote machine
cd /tmp
./upload-files.sh
#run commands on remote machine
ssh -t -t myuser:mypass#somewhere.com<<EOF
cd /tmp/uploads
./process-uploads.sh
exit
EOF
#run command locally again.
cd -
echo 'complete!'
If you want to run only one command:
ssh myuser:mypass#somewhere.com 'cd /tmp/uploads; ./process-uploads.sh'

use cygwin from cmd.exe

is it possible to use cygwin from cmd.exe in Windows?
i want to do following
FOR /L %G in (1 1 100) DO sshpass -p "password" scp E:\in\File%G.csv openstack#remotecomp:/testfiles/
transfer 100 files from windows to unix computer
now question:
can i use sshpass and scp from cmd.exe as long as cygwin is installed? or do i have to use cygwin terminal?
and do the files which i want to transfer neccessarily have to be in cygwin's folder?
goal is to use this one command in a BPEL activity, and as such there should not be any kind of user interaction when the command is run
You can use the full paths to the binaries, or create a wrapper script and call that to do the cygwin commands, e.g.
#!/bin/bash
# doit.sh wrapper script in home dir of cygwin user
echo "got args $#"
and call it from windows shell with
for /L %G in (1 1 100) DO c:\cygwin\bin\bash --login -c "/home/youruser/doit.sh %G"
in this case it prints 1..100 out, but your wrapper script can do all the ssh stuff it needs to instead.
For a more complex script, you can pass params from windows to the shell script like this:
#!/bin/bash
# callssh.sh
COUNT_NUM=$1
PASSWORD=$2
FILE_PATH=$(cygpath $3)
sshpass -p $PASSWORD scp $FILE_PATH openstack#whereever:/some/path/
and you'd call it with
for /L %G in (1 1 100) DO c:\cygwin\bin\bash --login -c "/home/youruser/callssh.sh %G your_password E:/in/File%G.csv"
Note the use of cygpath to convert from windows path style to something that cygwin understands. The SSH executable is a cygwin process so you need to convert to something it will be able to use.
Also, note the change from backslashes to forward slashes, again for some quirks in path separators between windows and cygwin.
If you have trouble with this (I can't test your code for you directly), then do this on a cygwin shell:
cygpath E:/path/to/file
and then check it outputs something like /e/path/to/file (or /cygpath/e/path/to/file if you haven't remapped our root drives).

Resources