I want to write a program that can capture the input/output of a pseudo terminal without it affecting the original terminal. It can be likened to pointing script to a /dev/pts/<n>.
Use Case: A user ssh's into my machine and runs an interactive tool. With audit, I can see commands running but I need to see the output also. I can listen in on /dev/pts/<n> but then the original logged in user does not get the output.
I want to write my own program to handle this case. Is this problem actually solvable and if so, where should I be looking to find a solution?
That's solvable by using ptrace(2) on the ssh server process which handles to master end of the pseudo-terminal (which is usually the parent process of the shell running in the terminal).
You can start with strace which is itself using ptrace(2), e.g.
strace -p <pid> -e trace=read,write \
-e read=<fds opened to /dev/ptmx> \
-e write=<fds opened to /dev/ptmx>
This will show you everything that's read or written to that pseudo-terminal. You can get the "fds opened to /dev/ptmx" from ls -l /proc/<pid>/fd.
You can then look at what strace is doing -- e.g. by stracing strace itself with
strace -e trace=ptrace,process_vm_readv strace ...
and by studying its source code.
You can of course modify the ssh server itself to log all that info, or just tweak its config options (e.g. LogLevel -- which can be modified on a per-user or connecting host basis).
Related
Well, I will put it plain and simple: I am a C++ pleb. Still trying to learn though.
My question is: is it possible to run a command though the terminal using system() command without letting the command be shown in the console/terminal?
Example:
system("sudo service sshd start") ;
Output: Sudo service sshd start
Where as I want:
system("sudo service sshd start") ;
output: (Blank)
Note: I am on linux.
The system standard library function starts up a subshell and executes the provided string as a command within that subshell. (Note that a subshell is simply a process running a shell interpreter; the particular shell interpreter invoked by system will depend on your system. No terminal emulator is used; at least, not on Unix or Unix-like systems.)
The system function does not reassign any file descriptors before starting the subshell, so the command executes with the current standard input, output and error assignments. Many commands will output to stdout and/or stderr, and those outputs will not be supressed by system.
If you want the command to execute silently, then you can redirect stdout and/or stderr in the command itself:
system("sudo service sshd start >>/dev/null 2>>/dev/null") ;
Of course, that will hide any error messages which might result from the command failing, so you should check the return value of system and provide your own error message (or log the information) if it is not 0.
This really has very little to do with the system call or the fact that you are triggering the subshell from within your own executable. The same command would have the same behaviour if typed directly into a shell.
I have developed a c++ app that runs on debian jessie server. Since I'm quite new in linux distros and specially the server ones that provide only terminal, I 'd like to find out if there is a way to watch the %CPU and %MEM on the same time that the c++ app runs. I tried to run
./C++_APP & ps -aux | grep .C++_APP
but ps ran only at the beginning. Is this possible somehow either with ps or with another command?
Use watch. You can pass your ps (along with its arguments) to it. If you don't run your application as a background process you will have to use a second terminal session or pipe the results to a file that you can look at later on.
You can use/install htop.
Set filter to match your executable name.
You may try that:
./C++_APP & wait && PID=`pidof -s -x C++_APP` && top -b -p $PID
It will display stats every second.
To break CTRL+C
To kill your app type than
kill $PID
I have built a bash script to start up some processes in my system. It simply calls the process and associated config file. Same as I would call from the command line.
#!/bin/bash
# Start specified process in a new session
setsid $1 &>/dev/null &
So to start up someprocess, I would call from the command line:
root#supercomputer:~# start someprocess
This works like a charm. Every process, every time. But when I make a system call from a different running C++ process, someprocess never starts up.
system( "start someprocess" )
This approach for 90% of my processes, except for one. The only difference in the working and not working processes is that the non-working one uses proprietary libraries underneath. I recently added the setsid option to the bash script in hopes that starting a new session would help, but it made no difference. I've also tried popen, and execv. No change.
So my question is what is the difference between calling something with system() and just making that same call from the command line?
All processes are written in C++ on Linux.
.bashrc is only invoked if bash is run as interactive, non-login shell. If it's invoked as non-interactive shell, as when using system() on a script with a bash shebang, it only reads the configuration file pointed to by $BASH_ENV.
That means you have the following options:
add -l to the shebang - causes the shell to read ~/.profile at startup
set $BASH_ENV to the script you want sourced before calling system()
add -i to the shebang - invokes bash as interactive shell and causes it to read ~/.bashrc, but will also effect how bash handles input/output.
I'd recommend the first option.
You can find a detailed explanation of how bash reads it's startup files here. I'm not sure this will solve your problem completely, but it may at leas shed some light on that part of the issue.
Check the environment variables that are used in the system() call. For example, call system to print out some of the variables, and see if they match what you see from the command line.
Likely they are not being sourced correctly.
I'm trying to setup my gdbinit to make gdb automatically attach to a certain program on a remote machine.
My script is something like:
define hook-run
target extended-remote | ssh -T remotemachine gdbserver --multi -
attach $pid
... <additional complicated stuff here>
end
My problem, of course, is that I'm missing $pid. I can find it by running ssh remotemachine ps | grep myprogram, but I'm not sure how to run that from within the gdb script and assign it into that $pid variable. How can I do that? I'm guessing I'm going to need some Python here...
I can find it by running ssh remotemachine ps | grep myprogram
I believe your choices are
use Python, or
escape to shell
For (2) you can use something like:
define hook-run
shell gen-remote-run.sh > .remote-cmd.gdb
source .remote-cmd.gdb
end
and put all the "magic" of figuring out remote PID into gen-remote-run.sh
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.