When I do
find /
on a terminal and then do on another terminal
lsof -a -d 0-2 -c fin
I see o/p listed from execution of lsof command.
But when I do
echo hi ; read -t 30 hello
hi
on the same terminal ( as find) and do (on different terminal)
lsof -a -d 0-2 -c read
I don't get any output from lsof command
Why ? Is it because read is bash built in ? Whats happening here ?
You got it right. "read" is a shell built-in. The process name remains sh (or bash, or zsh, or whatever else is your shell of choice).
Moreover, though for some shell built-ins there are binary alternatives, there isn't one for read. Really because of its syntax, it takes in the name of a shell variable that gets assigned the result of reading from the stdin. If it was an external program, it could never set the variable in the calling shell.
Related
I'd like to run a linux console command from a terminal, preventing it from accessing the TTY by itself (which will, for example, happen often when the console command tries to request a password from the user - this should just fail). The closest I get to a solution is using this wrapper:
temp=`mktemp -d`
echo "$#" > $temp/run.sh
mkfifo $temp/out $temp/err
setsid sh -c "sh $temp/run.sh > $temp/out 2> $temp/err" &
cat $temp/err 1>&2 &
cat $temp/out
rm -f $temp/out $temp/err $temp/run.sh
rmdir $temp
This runs the command as expected without TTY access, but passing the stdout/stderr output through the FIFO pipes does not work for some reason. I end up with no output at all even though the process wrote to stdout or stderr.
Any ideas?
Well, thank you all for having a look. Turns out that the script already contained a working approach. It just contained a typo which caused it to fail. I corrected it in the question so it may serve for future reference.
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.
in a shell script i have a command like, pid -p PID, after that i have some more commands. but as soon as the pid -p PID command runs we should supply a control+C to exit from it and then only the further commands executes. so i wanna do this periodically, i have all the things i want in a shell script and i wanna put this into crontab. the only thing that bothers is, if i schedule this script in the crontab, afetr its first execution, the command pid -p PID, how will i supply the CONTRO+C command for allowing further commands to execute???? please help
my script is like this.. very simple one
top -p $1
free -m
netstat -antp|grep 3306|grep $1
jmap -dump:file=my_stack$RANDOM.bin $1
You can send signals with kill. In your case however, you can just restrict top to one or a few iterations
top -p $1 -n 1
Update:
You can redirect the output of a command to a file. Either overwrite the file each time
command.sh >file.txt 2>&1
or append to a file
command.sh >>file.txt 2>&1
If you don't want the error output, leave out the 2>&1 part.
pid -p PID &
some_pid=$!
kill -s INT $some_pid
My problem is specific to the running of SPECCPU2006(a benchmark suite).
After I installed the benchmark, I can invoke a command called "specinvoke" in terminal to run a specific benchmark. I have another script, where part of the codes are like following:
cd (specific benchmark directory)
specinvoke &
pid=$!
My goal is to get the PID of the running task. However, by doing what is shown above, what I got is the PID for the "specinvoke" shell command and the real running task will have another PID.
However, by running specinvoke -n ,the real code running in the specinvoke shell will be output to the stdout. For example, for one benchmark,it's like this:
# specinvoke r6392
# Invoked as: specinvoke -n
# timer ticks over every 1000 ns
# Use another -n on the command line to see chdir commands and env dump
# Starting run for copy #0
../run_base_ref_gcc43-64bit.0000/milc_base.gcc43-64bit < su3imp.in > su3imp.out 2>> su3imp.err
Inside it it's running a binary.The code will be different from benchmark to benchmark(by invoking under different benchmark directory). And because "specinvoke" is installed and not just a script, I can not use "source specinvoke".
So is there any clue? Is there any way to directly invoke the shell command in the same shell(have same PID) or maybe I should dump the specinvoke -n and run the dumped materials?
You can still do something like:
cd (specific benchmark directory)
specinvoke &
pid=$(pgrep milc_base.gcc43-64bit)
If there are several invocation of the milc_base.gcc43-64bit binary, you can still use
pid=$(pgrep -n milc_base.gcc43-64bit)
Which according to the man page:
-n
Select only the newest (most recently started) of the matching
processes
when the process is a direct child of the subshell:
ps -o pid= -C=milc_base.gcc43-64bit --ppid $!
when not a direct child, you could get the info from pstree:
pstree -p $! | grep -o 'milc_base.gcc43-64bit(.*)'
output from above (PID is in brackets): milc_base.gcc43-64bit(9837)
I have a script like this?
command='scp xxx 192.168.1.23:/tmp'
su - nobody -c "$command"
The main shell didn't print any info.
How can I get output from the sub command?
You can get all of its output by just redirecting the corresponding output channel:
command='scp ... '
su - nobody -c "$command" > file
or
var=$(su - nobody -c "$command")
But if you don't see anything, maybe the diagnostics output of scp is disabled?
Is there a "-q" option somewhere in your real command?
You aren't actually running the scp. When you use the
VAR=value cmd ...
syntax, the VAR=value setting goes into the environment of cmd but it's not available in the current shell. The command after your -c is empty, or the previous value of $command if there was one.