How to get value at a memory address in linux shell - linux

I know that we can get the value at a memory address through a C program or gdb.
Is there any way to get it by bash shell or something like "one-line" perl instruction?

Short answer... No
If you were very careful it MIGHT be possible to pass instructions into GDB and interpret the output. Look at rocky's answer if you want to try.
Its part of the unix process model that one process cannot see inside another and cannot read each other's memory. This is for security. There is a special kernal API which can be used to see into programs. But there are very few clients for this API. Off the top of my head GDB is the only one I know.
I suspect that what you're trying to achieve is either a really bad idea or can be done without reading a program's memory.

The following possibly gets close to what you may want. And if not, hopefully you'll be able to adapt.
I'll say at the outset though that you are extremely vague at what you mean by "memory address". Below I am going to take that to mean the address of the current instruction executed which I will use the gdb command "backtrace" to get. Adapt the gdb command from "bt" to whatever it is you were thinking of to get the "memory address".
Let's say your program is sleeper-for-pid with process id 3963
sudo gdb --ex 'bt 1' --batch -nx -p 3963
will run gdb attached to the process and give a backtrace of the most recent entry. Here is an example:
sudo gdb --ex 'bt 1' --batch -nx -p 3963
84 ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) #0 0x00007f5dee71f2f0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:84
If you really just want the line with the address, you'd grep for #0, e.g.
sudo gdb --ex 'bt 1' --batch -nx -p 3963 | grep '#0'
(gdb) #0 0x00007f5dee71f2f0 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:84
And if you just want the address you might have to do a further cut, e.g.
$ sudo gdb --ex 'bt 1' -nx -p 3963| grep '#0' | cut -d' ' -f 4
0x00007f5dee71f2f0
If you don't know the process id, you might be able to use pidof. For example if the command name is sleeper-for-pid:
$ sudo gdb --ex 'bt 1' --batch -nx -p $(pidof sleeper-for-pid)
And "sudo" may or may not work for you or be needed.
Personally, instead of just the most recent backtrace entry I prefer more than that. So bt 1 might get adjusted to bt 3 or bt for a more full back trace.
Hopefully this is enough to get you started .

I know that we can get the value at a memory address through a C program or gdb Are there any way to get it by bash shell or something like "one-line" perl instruction??
A shell is just a program. What you asking to do is rather meaningless. Assuming a shell did allow you to inspect a memory address (and you could easily modify a shell or write your own to do so), The value of a memory address is for the shell's process. Any other process is going to have a different memory value at the same address.

Related

Get stdout from other program in Linux

I want in Linux, get the stdout of a NodeJS program that is opened, from other NodeJS program or bash.
I have the PID, or name of program and the data, put to function in real time.
Maybe touching files in /proc?
This is possible?
You can use strace -e write -p <pid> to see what output is the program writing to stdout (or other FDs) in real time. It does not show what has been written earlier and it needs a little parsing to extract clean stdout contents.
By default, it truncates shown writes to only 32 characters. To show more, use -s switch:
strace -e write -s 9999 -p <pid>

How to find the PID of a running command in bash?

I've googled this question, but never found anything useful for my particular case.
So, what I'm trying to figure out is the PID of a certain command that is running so I can kill it if necessary. I know it's possible to get the PID of a command by typing echo $! So supposedly
my_command & echo $!
should give me the PID. But this isn't the case, and I think I know why:
My command is as follows:
screen -d -m -S Radio /path/to/folder -f frequency -r path/to/song
which opens a detached screen first and then types the command so that it gets executed and keeps on running in the background. This way the PID that echo shows me is the wrong one. I'm guessing it shows me PID of screen -d -m -S Radio /path/to/folder -f frequency -r path/to/song instead of the PID of the command run in the new terminal created by screen.
But there's another problem to it: when I run screen -ls in the terminal, the command that is running in the background doesn't show up! I'm fairly certain it's running because the Pi is constantly at 25% CPU usage (instead of the 0% or 1% usually) and when I type ps au I can actually see the command and the PID.
So now I'm calling the community: any idea on how I could find the PID of that certain command in the new terminal? I'm writing a bash script, so it has to be possible to obtain the PID through code. Perfect would be a command that stores the PID in a variable!
Thanks to #glennjackman I managed to get the PID I wanted with a simple pgrep search_word. At first it wasn't working, but somehow I made it work after some trial and error. For those wanting the PID on a variable, just type
pid=$(pgrep search_word)
Regarding the problem with screen -ls not showing my detached session, it's still not solved, but I'm not bothered with it. Thanks again for solving my problem #glennjackman !
EDIT:
Second problem solved, check the comments on berends answer.
You can easily find out all the running process and their PID by writing (for example):
ps aux
The process is run by screen so you can probably find it easier by writing:
ps aux | grep screen
For more info about ps and the parameters I used check (quick google) -> https://www.lifewire.com/g00/uses-of-linux-ps-command-4058715?i10c
EDIT: You can use this command with bash scripting as well.

"Permission denied" reading from a process-substitution FIFO in an unprivileged child process

Consider the following, observed with bash 4.4 on a Linux 3.19 kernel:
# in reality, this may access files "nobody" isn't allowed
get_a_secret() { printf '%s\n' "This is a secret"; }
# attach a process substitution reading the secret to FD 10
exec 10< <(get_a_secret)
# run a less-privileged program that needs the secret, passing it the file descriptor.
chpst -u nobody:nobody -- cat /dev/fd/10
...or the shorter/simpler:
chpst -u nobody:nobody -- cat <(get_a_secret)
Either fails in a manner akin to the following:
cat: /proc/self/fd/10: Permission denied
So, two branches to this question:
What's going on here?
Is there a way to get the desired behavior (passing the ability to read the secret through to the single child process being invoked in a way that doesn't persistently expose that secret to other processes running as "nobody") without exposing the FIFO's output to other processes?
(Yes, I'm well aware that I need to lock down ptrace and /proc/*/mem to prevent another process running as "nobody" from pulling the secret out of the client as it's being read; that said, that's (1) something I can do, and (2) when the process is only run before any potentially-attacker-controlled executables are invoked, less exposure than allowing any process running as nobody to pull the secret out of /proc/*/environ for the full duration of that process).
The following workaround avoids this issue:
exec 10< <(get_a_secret)
chpst -u nobody:nobody -- sh -c 'cat <&10'
Note the redirection being written as <&10 -- not </dev/fd/10 or </proc/self/fd/10 (on platforms which provide /dev/fd -- on platforms without this facility, bash rewrites it into a fdup2() call).
An answer with an explanation of the behavior (and perhaps a workaround that allows programs that don't accept a FD number as input to act on the read side?) would be in a position to supercede this one. :)

linux: redirect stdout after the process started [duplicate]

I have some scripts that ought to have stopped running but hang around forever. Is there some way I can figure out what they're writing to STDOUT and STDERR in a readable way?
I tried, for example, to do:
$ tail -f /proc/(pid)/fd/1
but that doesn't really work. It was a long shot anyway.
Any other ideas?
strace on its own is quite verbose and unreadable for seeing this.
Note: I am only interested in their output, not in anything else. I'm capable of figuring out the other things on my own; this question is only focused on getting access to stdout and stderr of the running process after starting it.
Since I'm not allowed to edit Jauco's answer, I'll give the full answer that worked for me (Russell's page relies on un-guaranteed behaviour that, if you close file descriptor 1 for STDOUT, the next creat call will open FD 1.
So, run a simple endless script like this:
import time
while True:
print 'test'
time.sleep(1)
Save it to test.py, run with
$ python test.py
Get the PID:
$ ps auxw | grep test.py
Now, attach gdb:
$ gdb -p (pid)
and do the fd magic:
(gdb) call creat("/tmp/stdout", 0600)
$1 = 3
(gdb) call dup2(3, 1)
$2 = 1
Now you can tail /tmp/stdout and see the output that used to go to STDOUT.
There's several new utilities that wrap up the "gdb method" and add some extra touches. The one I use now is called "reptyr" ("Re-PTY-er"). In addition to grabbing STDERR/STDOUT, it will actually change the controlling terminal of a process (even if it wasn't previously attached to a terminal).
The best use of this is to start up a screen session, and use it to reattach a running process to the terminal within screen so you can safely detach from it and come back later.
It's packaged on popular distros (Ex: 'apt-get install reptyr').
http://onethingwell.org/post/2924103615/reptyr
GDB method seems better, but you can do this with strace, too:
$ strace -p <PID> -e write=1 -s 1024 -o file
Via the man page for strace:
-e write=set
Perform a full hexadecimal and ASCII dump of all the
data written to file descriptors listed in the spec-
ified set. For example, to see all output activity
on file descriptors 3 and 5 use -e write=3,5. Note
that this is independent from the normal tracing of
the write(2) system call which is controlled by the
option -e trace=write.
This prints out somewhat more than you need (the hexadecimal part), but you can sed that out easily.
I'm not sure if it will work for you, but I read a page a while back describing a method that uses gdb
I used strace and de-coded the hex output to clear text:
PID=some_process_id
sudo strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $PID -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p"
I combined this command from other answers.
strace outputs a lot less with just -ewrite (and not the =1 suffix). And it's a bit simpler than the GDB method, IMO.
I used it to see the progress of an existing MythTV encoding job (sudo because I don't own the encoding process):
$ ps -aef | grep -i handbrake
mythtv 25089 25085 99 16:01 ? 00:53:43 /usr/bin/HandBrakeCLI -i /var/lib/mythtv/recordings/1061_20111230122900.mpg -o /var/lib/mythtv/recordings/1061_20111230122900.mp4 -e x264 -b 1500 -E faac -B 256 -R 48 -w 720
jward 25293 20229 0 16:30 pts/1 00:00:00 grep --color=auto -i handbr
$ sudo strace -ewrite -p 25089
Process 25089 attached - interrupt to quit
write(1, "\rEncoding: task 1 of 1, 70.75 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.76 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.77 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.78 % "..., 73) = 73^C
You can use reredirect (https://github.com/jerome-pouiller/reredirect/).
Type
reredirect -m FILE PID
and outputs (standard and error) will be written in FILE.
reredirect README also explains how to restore original state of process, how to redirect to another command or to redirect only stdout or stderr.
You don't state your operating system, but I'm going to take a stab and say "Linux".
Seeing what is being written to stderr and stdout is probably not going to help. If it is useful, you could use tee(1) before you start the script to take a copy of stderr and stdout.
You can use ps(1) to look for wchan. This tells you what the process is waiting for. If you look at the strace output, you can ignore the bulk of the output and identify the last (blocked) system call. If it is an operation on a file handle, you can go backwards in the output and identify the underlying object (file, socket, pipe, etc.) From there the answer is likely to be clear.
You can also send the process a signal that causes it to dump core, and then use the debugger and the core file to get a stack trace.

How can a process intercept stdout and stderr of another process on Linux?

I have some scripts that ought to have stopped running but hang around forever. Is there some way I can figure out what they're writing to STDOUT and STDERR in a readable way?
I tried, for example, to do:
$ tail -f /proc/(pid)/fd/1
but that doesn't really work. It was a long shot anyway.
Any other ideas?
strace on its own is quite verbose and unreadable for seeing this.
Note: I am only interested in their output, not in anything else. I'm capable of figuring out the other things on my own; this question is only focused on getting access to stdout and stderr of the running process after starting it.
Since I'm not allowed to edit Jauco's answer, I'll give the full answer that worked for me (Russell's page relies on un-guaranteed behaviour that, if you close file descriptor 1 for STDOUT, the next creat call will open FD 1.
So, run a simple endless script like this:
import time
while True:
print 'test'
time.sleep(1)
Save it to test.py, run with
$ python test.py
Get the PID:
$ ps auxw | grep test.py
Now, attach gdb:
$ gdb -p (pid)
and do the fd magic:
(gdb) call creat("/tmp/stdout", 0600)
$1 = 3
(gdb) call dup2(3, 1)
$2 = 1
Now you can tail /tmp/stdout and see the output that used to go to STDOUT.
There's several new utilities that wrap up the "gdb method" and add some extra touches. The one I use now is called "reptyr" ("Re-PTY-er"). In addition to grabbing STDERR/STDOUT, it will actually change the controlling terminal of a process (even if it wasn't previously attached to a terminal).
The best use of this is to start up a screen session, and use it to reattach a running process to the terminal within screen so you can safely detach from it and come back later.
It's packaged on popular distros (Ex: 'apt-get install reptyr').
http://onethingwell.org/post/2924103615/reptyr
GDB method seems better, but you can do this with strace, too:
$ strace -p <PID> -e write=1 -s 1024 -o file
Via the man page for strace:
-e write=set
Perform a full hexadecimal and ASCII dump of all the
data written to file descriptors listed in the spec-
ified set. For example, to see all output activity
on file descriptors 3 and 5 use -e write=3,5. Note
that this is independent from the normal tracing of
the write(2) system call which is controlled by the
option -e trace=write.
This prints out somewhat more than you need (the hexadecimal part), but you can sed that out easily.
I'm not sure if it will work for you, but I read a page a while back describing a method that uses gdb
I used strace and de-coded the hex output to clear text:
PID=some_process_id
sudo strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $PID -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p"
I combined this command from other answers.
strace outputs a lot less with just -ewrite (and not the =1 suffix). And it's a bit simpler than the GDB method, IMO.
I used it to see the progress of an existing MythTV encoding job (sudo because I don't own the encoding process):
$ ps -aef | grep -i handbrake
mythtv 25089 25085 99 16:01 ? 00:53:43 /usr/bin/HandBrakeCLI -i /var/lib/mythtv/recordings/1061_20111230122900.mpg -o /var/lib/mythtv/recordings/1061_20111230122900.mp4 -e x264 -b 1500 -E faac -B 256 -R 48 -w 720
jward 25293 20229 0 16:30 pts/1 00:00:00 grep --color=auto -i handbr
$ sudo strace -ewrite -p 25089
Process 25089 attached - interrupt to quit
write(1, "\rEncoding: task 1 of 1, 70.75 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.76 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.77 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.78 % "..., 73) = 73^C
You can use reredirect (https://github.com/jerome-pouiller/reredirect/).
Type
reredirect -m FILE PID
and outputs (standard and error) will be written in FILE.
reredirect README also explains how to restore original state of process, how to redirect to another command or to redirect only stdout or stderr.
You don't state your operating system, but I'm going to take a stab and say "Linux".
Seeing what is being written to stderr and stdout is probably not going to help. If it is useful, you could use tee(1) before you start the script to take a copy of stderr and stdout.
You can use ps(1) to look for wchan. This tells you what the process is waiting for. If you look at the strace output, you can ignore the bulk of the output and identify the last (blocked) system call. If it is an operation on a file handle, you can go backwards in the output and identify the underlying object (file, socket, pipe, etc.) From there the answer is likely to be clear.
You can also send the process a signal that causes it to dump core, and then use the debugger and the core file to get a stack trace.

Resources