I want to run xterm terminal in C++ to create a Linux process like this
system("xterm -e adb start-server")
The adb process is created but after that command it gets killed. I was trying to solve this problem by using nohup and screen but nothing works. I know that I have to put the adb process into background, but how to do that with xterm?
Edit:
I'm loking for solution that will terminate/close the xterm window, but not the adb process. Later I want to use multiple commands in the same xterm window like
system("xterm -e \"adb start-server; adb connect 192.168.X.XXX;\"");
and all output (and eventually errors) I want to see in the same xterm.
You can do it like this:
xterm -e /bin/bash -c "adb start-server; /bin/bash"
Related
So basiclly im trying to use this:
int main()
{
system("adb kill-server \n"
"adb devices \n"
"adb start-server & \n"
"var=$(adb shell \"pidof com.rok\")\n"
"AFTER=`echo $var | sed 's/\\r//g'`\n"
"echo \"$AFTER\"\n"
"adb shell \"kill -STOP $AFTER\"\n"
"adb shell sleep 2\n"
"adb shell \"kill -CONT $AFTER\"");
return 0;
}
thing is this works in Clion without any error, but i must do this in visual studio and in visual studio i cannot do it like that i have to do every system command alone like:
system("adb kill-server");
system("adb devices");
system("adb start-server");
system("var=$(adb shell \"pidof com.rok\")");
system("AFTER=`echo $var | sed 's/\\r//g'`");
system("adb shell \"kill -STOP $AFTER\"");
so now the thing is when i run it like this everything works except this two lines:
system("var=$(adb shell \"pidof com.rok\")");
system("AFTER=`echo $var | sed 's/\\r//g'`");
even though they perfectly works on clion they dont in visual studio, i cannot find a way to solve this problem, this is the error:
'var' is not recognized as an internal or external command,
operable program or batch file.
'AFTER' is not recognized as an internal or external command,
operable program or batch file.
can anyone explain why this happens? and how can i solve this problem?
Each call of system() creates it's own shell as a subprocess, that's why multiple subsequent system() calls don't work if you e.g. try to set shell variables or do a cd command (expecting subsequent commands running in a specific directory).
The easiest way to do it, is to create a little temporary script file containing all the commands and execute this one with a single system() call:
// A raw string literal to make escaping easier
// (see https://en.cppreference.com/w/cpp/language/string_literal)
std::string cmds = R"xxx(
adb kill-server
adb devices
adb start-server &
var=$(adb shell "pidof com.rok")
AFTER=`echo $var | sed 's/\r//g'`
echo "$AFTER"
adb shell "kill -STOP $AFTER"
adb shell sleep 2
adb shell "kill -CONT $AFTER"
)xxx";
std::ofstream cmdFile("tempCmdFile.cmd");
cmdFile << cmds;
cmdFile.close();
system("tempCmdFile.cmd");
You probably should tidy up the tempCmdFile.cmd up afterwards (i.e. remove it). But I hope you grasp what the code above does.
Also I am not so sure that
AFTER=`echo $var | sed 's/\r//g'`
will work in a windows shell, as you expect it to do. You probably need a different solution for that, or a *nix like shell to run it (e.g. MinGw provides one).
If I have an MPI program that I want to debug with gdb while being able to see all of the separate processes' outputs, I can use:
mpirun -n <NP> xterm -hold -e gdb -ex run --args ./program [arg1] [arg2] [...]
which is well and good when I have a GUI to play with. But that is not always the case.
Is there a similar set up I can use with screen such that each process gets its own window? This would be useful for debugging in a remote environment since it would allow me to flip between outputs using Ctrl+a n.
I think this answer in the "How do I debug an MPI program?" thread does what you want.
EDITS:
In response to the comment, you can do it somewhat more easily, although succinct isnt exactly the term I would use:
Launch a detached screen via mpirun - running your debugger and process. I've called the session mpi, and im passing through my library path because it gets stripped by screen and my demo needs it (also I'm on a mac, hence lldb and DYLD):
mpirun -np 4 screen -AdmS mpi env DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH lldb demo.out
Then launch a seperate screen session, which i've called 'debug':
screen -AdmS debug
Use screen -ls to list the running sessions:
>> screen -ls
There are screens on:
19871.mpi (Detached)
19872.mpi (Detached)
19875.mpi (Detached)
19876.mpi (Detached)
20105.debug (Detached)
Now launch 4 new tabs in the debug session, attaching each to one of the mpi sessions:
screen -S debug -X screen -t tab0 screen -r 19871.mpi
screen -S debug -X screen -t tab1 screen -r 19872.mpi
screen -S debug -X screen -t tab2 screen -r 19875.mpi
screen -S debug -X screen -t tab3 screen -r 19876.mpi
Then simply attach to your debug session with screen -r debug. Now you have 4 tabs, each running a serial instance of the debugger attached to an mpi process similarly to the xterm method you described before. Its not exactly the quickest set of commands, but at least you dont need to modify your code or chase PIDs etc.
Another method I tried, but doesnt seem to work:
Launch a detached screen
screen -AdmS ashell
Launch two mpi processes that start new screen tabs in the detached session, launching lldb with my demo mpi application:
mpirun -np 1 screen -S ashell -X screen -t tab1 env DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH lldb demo.out : -np 1 screen -S ashell -X screen -t tab2 env DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH lldb demo.out
Or alternatively just
mpirun -np 2 screen -S ashell -X screen env DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH lldb demo.out
Then attach to screen with
screen -r ashell
And you'll have 3 tabs, 2 of them running lldb with your program, and one with whatever your standard shell is. Unfortunately when you try running the programs, each process thinks its the only one in the comm world, and im not sure what to do about that...
How do you debug a C/C++ MPI program?
One way is to start a separate terminal and gdb session for each of the
processes:
mpirun -n <NP> xterm -hold -e gdb -ex run --args ./program [arg1] [arg2] [...]
where NP is the number of processes.
What if you don't have a GUI handy?
(See below for a handy script.)
This is based on timofiend's answer here.
Spin up the mpi program in its debugger in a number of screen sessions:
mpirun -np 4 screen -AdmS mpi gdb ./parallel_pit_fill.exe one retain ./beauford.tif 500 500
Spin up a new screen session to access the debugger:
screen -AdmS debug
Load the debugger's screen sessions in to the new screen session
screen -list | #Get list of screen sessions
grep -E "[0-9]+.mpi" | #Extract the relevant ones
awk '{print NR-1,$1}' | #Generate tab #s and session ids, drop rest of the string
xargs -n 2 sh -c '
screen -S debug -X screen -t tab$0 screen -r $1
'
Jump into the new screen session:
screen -r debug
I've encapsulated the above in a handy script:
#!/bin/bash
if [ $# -lt 2 ]
then
echo "Parallel Debugger Syntax: $0 <NP> <PROGRAM> [arg1] [arg2] [...]"
exit 1
fi
the_time=`date +%s` #Use this so we can run multiple debugging sessions at once
#(assumes we are only starting one per second)
#The first argument is the number of processes. Everything else is what we want
#to run. Make a new mpi screen for each process.
mpirun -np $1 screen -AdmS ${the_time}.mpi gdb "${#:2}"
#Create a new screen for debugging from
screen -AdmS ${the_time}.debug
#The following are used for loading the debuggers into the debugging screen
firstpart="screen -S ${the_time}.debug"
secondpart=' -X screen -t tab$0 screen -r $1'
screen -list | #Get list of mpi screens
grep -E "[0-9]+.${the_time}.mpi" | #Extract the relevant ones
awk '{print NR-1,$1}' | #Generate tab #s and session ids, drop rest of the string
xargs -n 2 sh -c "$firstpart$secondpart"
screen -r ${the_time}.debug #Enter debugging screen
You can have a look at tmpi, which automates what the other answers show how to achieve, but using tmux instead of screen.
And as a bonus, it multiplexes your keyboard input to all MPI ranks!
I do this:
popen("xterm -e ' some bash script ' ","r");
and it works fine if I launch my application from a terminal command line.
but if I double click in the finder to launch it (i.e. non terminal), the application runs, but the xterm doesn't appear.
(xterm is maybe not the right solution on osx, what I want to do is to open a terminal from popen, interact with the user inside the terminal, and return the result of this interaction to the main program)
The output shown in xterm's window (or likely other terminals) will not be read by popen, so that part is unclear. However, you say that works from a terminal window.
Another problem is that the DISPLAY variable needed to run xterm may not be set in the environment where the finder is running. You can work around that by adding a suitable -display option to the command-line. For instance, if your application is running and displaying on the local machine (likely), you could try
popen("xterm -display :0.0 -e ' some bash script ' ","r");
When capturing output from xterm, there are two types of output to consider:
error messages from xterm itself are written to the standard error
the program running inside xterm, e.g., 'some bash script', will write to the xterm window.
For your example, you could capture the error messages in the pipe (from popen directly by redirecting the standard error in the command to xterm's standard output, e.g.,
popen("xterm -display :0.0 -e ' some bash script ' 2>&1 ","r");
Capturing the output of the bash script is harder. You could redirect the output of the bash script itself, e.g.,
popen("xterm -display :0.0 -e ' some bash script >mylogfile ' ","r");
but that interferes with interaction. A better solution might be to use the script program, doing something like this:
popen("xterm -display :0.0 -e script mylogfile ' some bash script ' ","r");
I have a image processing project in C++ using opencv. The program runs correctly and I get the desired output. However, I have some messages that I print out using the cout command. When I run the program using the terminal (./myprogram) the messages are displayed correctly. When I double click the executable file I get only the output (in my case a new video is created) But I do get the messages. How do I get the program to automatically prompt the messages when it is not run from the terminal.
PS: I use ubuntu 14.04
Create a script like this, lets call it run.sh:
#!/bin/sh
cd work_dir
./myProgram
read -r -p "Press any key..." key
Then do:
xterm -e run.sh
and make your desktop shortcut run this command instead of the program directly.
In Applescript, I have the following:
do shell script "/Applications/Vidalia.app/Contents/MacOS/Vidalia"
do shell script "/Applications/Firefox_3.6/Firefox.app/Contents/MacOS/firefox-bin -P Anon"
It works perfectly, but the issue is that it will wait for Vidalia to be CLOSED before it will then launch Firefox. I would like to open both at the same time with one script. I don't really understand the language and all of my searching has turned up nothing. How can I get these open simultaneously? That is the point, after all.
Any help is much appreciated.
Try using the open command to launch the applications:
do shell script "open /Applications/Vidalia.app"
do shell script "open /Applications/Firefox_3.6/Firefox.app --args -P Anon"
With do shell script, AppleScript will wait for the response of the process you're running. As you're calling it, there's no option but to wait for the process to terminate, which is when the application closes.
To solve this, you need to replace your shell commands with ones that provide no response and terminate right away. So try this:
do shell script "/Applications/Vidalia.app/Contents/MacOS/Vidalia &> /dev/null & /Applications/Firefox_3.6/Firefox.app/Contents/MacOS/firefox-bin -P Anon &> /dev/null &"
I didn't test this with the applications you're using, as I have neither installed; instead, I tested with iTunes and Bento, with which it worked as you're hoping.