I need a script to identify the files opened a particular process on linux
To identify fd :
>cd /proc/<PID>/fd; ls |wc –l
I expect to see a list of numbers which is the list of files descriptors' number using in the process. Please show me how to see all the files using in that process.
Thanks.
The command you probably want to use is lsof. This is a better idea than digging in /proc, since the command is a more clear and a more stable way to get system information.
lsof -p pid
However, if you're interested in /proc stuff, you may notice that files /proc/<pid>/fd/x is a symlink to the file it's associated with. You can read the symlink value with readlink command. For example, this shows the terminal stdin is bound to:
$ readlink /proc/self/fd/0
/dev/pts/43
or, to get all files for some process,
ls /proc/<pid>/fd/* | xargs -L 1 readlink
While lsof is nice you can just do:
ls -l /proc/pidoftheproces/fd
lsof -p <pid number here> | wc -l
if you don't have lsof, you can do roughly the same using just /proc
eg
$ pid=1825
$ ls -1 /proc/$pid/fd/*
$ awk '!/\[/&&$6{_[$6]++}END{for(i in _)print i}' /proc/$pid/maps
You need lsof. To get the PID of the application which opened foo.txt:
lsof | grep foo.txt | awk -F\ '{print $2}'
or what Macmede said to do the opposite (list files opened by a process).
lsof | grep processName
Related
I have a problem with cat. I want to write script doing the same thing as ps -e. In pid.txt i have PID of running processes.
ls /proc/ | grep -o "[0-9]" | sort -h > pid.txt
Then i want use $line like a part of path to cmdline for evry PID.
cat pid.txt | while read line; do cat /proc/$line/cmdline; done
i try for loop too
for id in 'ls /proc/ | grep -o "[0-9]\+" | sort -h'; do
cat /proc/$id/cmdline;
done
Don't know what i'm doing wrong. Thanks in advance.
I think what you're after is this - there were a few flaws with all of your approaches (or did you really just want to look at process with a single-digit PID?):
for pid in $(ls /proc/ | grep -E '^[0-9]+$'|sort -h); do cat /proc/${pid}/cmdline; tr '\x00' '\n'; done
You seem to be in a different current directory when running cat pid.txt... command compared to when you ran your ls... command. Run both your commands on the same terminal window, or use absolute path, like /path/to/pid.txt
Other than your error, you might wanna remove -o from your grep command as it gives you 1 digit for a matching pid. For example, you get 2 when pid is 423. #Roadowl also pointed that already.
Suppose, one process is running and accessing OPENSSL shared library to perform some operation. Is there any way to find the pid of this process ?
Is there any way to find on which core this process is running ?
If possible, does it require any special privilege like sudo etc?
OS- Debian/Ubuntu
Depending on what exactly you want, something like this might do:
lsof | grep /usr/lib64/libcrypto.so | awk '{print $1, $2}' | sort -u
This essentially:
uses lsof to list all open files on the system
searches for the OpenSSL library path (which also catches versioned names like libcrypto.so.1.0)
selects the process name and PID
removes any duplicate entries
Note that this will also output processes using previous instances of the shared library file that were e.g. updated to a new version and then deleted. It also has the minor issue of outputting duplicates when a process has multiple threads with different names.
And yes, this may indeed require elevated privileges, depending on the permissions on your /proc directory.
If you really do need the processor core(s), you could try something like this (credit to dkaz):
lsof | grep /usr/lib64/libcrypto.so | awk '{print $2}' |
xargs -r ps -L --no-headers -o pid,psr,comm -p | sort -u
Adding the lwp variable to the ps command would also show the thread IDs:
lsof | grep /usr/lib64/libcrypto.so | awk '{print $2}' |
xargs -r ps -L --no-headers -o pid,lwp,psr,comm -p
PS: The what-core-are-the-users-of-this-library-on requirement still sounds a bit unusual. It might be more useful if you mentioned the problem that you are trying to solve in broader terms.
thkala is almost right. The problem is that the answer is half, since it doesn't give the core.
I would run that:
$ lsof | grep /usr/lib64/libcrypto.so |awk '{print $2}' | xargs ps -o pid,psr,comm -p
I just recently updated my Ubuntu VM to 14.04 and before this I could run the grep command
grep -nr "piece of text"
or any other grep command for that matter and it would finish in 2-10 seconds in the directory I was working on. Now for some reason (no idea if this was caused by the update) running any grep command in the same dir I was working in just seems to hang there (idk if it does complete because I don't want to wait over a min or so for a search to happen) instead of showing my results. Any idea of what's happening or what I can do and try to fix it?
You aren't specifying the files to grep, so it's trying to read STDIN. I think you wanted
grep -nr "piece of text" *
Note the asterisk is globbed to all files in the current path.
which grep are you using ? -r option default to '.' directory in gnu case
which grep :
/bin/grep --version
/bin/grep (GNU grep) 2.18)
...
this is gnu grep :
echo "truc" >/tmp/truc
cd /tmp; grep -nr "truc";
using gnu grep -> it search recursively files in . of current directory ( here in /tmp ) and displays them containing "truc"
if /bin/grep --version is busybox :
BusyBox v1.22.1 (Debian 1:1.22.0-8) multi-call binary.
Usage:
grep [-HhnlLoqvsriwFEz] [-m N] [-A/B/C N] PATTERN/-e PATTERN.../-f FILE [FILE]...
using busybox : cd /tmp; busybox grep -nr "truc";
wait indefinitely that you type content of file on STDIN ( stop with Ctrl+C ).
it reads STDIN as a file ( not even caring that -n indicates a directory recursion ).
As others answered, and as POSIX grep or GNU grep documentation tells, you need to specify some file to the standard grep command. (But GNU grep defaults to current directory . if -r is given without a directory name; however if -r is not given at all, grep defaults to read - i.e. the stdin).
BTW, I would also recommend the ack utility, packaged as the ack-grep package on Ubuntu or Debian. It does not need any files (default is the source code files under current directory) and it avoids useless non-source files (version control or object files...):
ack "piece of text"
Also, under emacs, you can use M-x grep
Is there a way to figure out where in a file a program is reading from? It seems like might be doable with strace or dtrace?
To clarify the question and give motivation, say I have a 10GB log file and am counting the number of unique lines:
$ cat log.txt | sort | uniq | wc -l
Can I check where in the file cat is currently at, effectively giving the progress of the command? Using lsof, I can't seem to get the offset of last file read, which I think is what would do the trick:
$ lsof log.txt
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
cat 16021 erik 3r REG 0,22 13416118210 1078133219
Edit: I apologize, the example I gave is too narrow and misses the point. Ideally, for an arbitrary program, I would like to see where in the file reads are occurring (regardless of pipe).
You can do what you want with the progress command. It shows the progress of coreutils tools such as cat or other programs in reading their file.
File and offset information is available in Linux in /proc/<PID>/fd and /proc/<PID>/fdinfo.
Instead of cat :
pv log.txt | sort | uniq | wc -l
Piping with pv :
SIZE=$( ls -l log.txt | awk '{print $5}'); cat log.txt | sort | pv -s $SIZE | uniq | wc -l
If the example is truly your use case, then I'd recommend pipe viewer.
i have a sample code like this:
CMD="svn up blablabla | grep -v .tgz"
echo $CMD | xargs -n -P ${PARALLEL:=20} -- bash -c
the purpose is to run svn update in parallel. However when encounter the conflicts, which should prompt out several selection for users to choose, it just passes without waiting for user input. And an error is shown:
Conflict discovered in 'blablabla'.
Select: (p) postpone, (df) diff-full, (e) edit,
(mc) mine-conflict, (tc) theirs-conflict,
(s) show all options: svn: Can't read stdin: End of file found
Is there any way to fix this?
Thanks
Yes, there is a way to fix this! See the answer to how to prompt a user from a script run with xargs. Long story short, use
xargs -a FILENAME your_script
or
xargs -a <(cat FILENAME) your_script
The first version actually reads lines from a file, and the second one fakes reading lines from a file, which is convenient for using xargs in pipe chains with awk or perl. Remember to use the -0 flag if you don't want to break on whitespace!
Another solution, which doesn't rely on Bash but on GNU's flavor of xargs, is to use the -o or --open-tty option:
echo $CMD | xargs -n -P ${PARALLEL:=20} --open-tty -- bash -c
From the manpage:
-o, --open-tty
Reopen stdin as /dev/tty in the child process before executing the command. This is use‐
ful if you want xargs to run an interactive application.