2

Let's say:

xb@dnxb:/tmp$ echo 'ls -l /proc/$$/fd | grep a.sh' > a.sh; \
> while IFS='' read -r f; do \
> echo "$f"; "$f" a.sh; \
> done < <(tail -n +2 /etc/shells)
/bin/sh
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
/bin/dash
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
/bin/bash
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 255 -> /tmp/a.sh
/bin/rbash
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 255 -> /tmp/a.sh
/bin/zsh
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 11 -> /tmp/a.sh
/usr/bin/zsh
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 11 -> /tmp/a.sh
/bin/ksh93
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
/bin/rksh93
lr-x------ 1 xiaobai xiaobai 64 Jan  20 00:09 10 -> /tmp/a.sh
xb@dnxb:/tmp$ 

Does bash always has fixed fd number 255 and zsh has fixed fd number 11 by default ?

I ask this question because I need to extract the full path executed from any shell processes. I wonder I can hard-coded my script to refer this fixed numbers or not.

Note that this is for personal script and not means to run on critical business, so I'm not looking for 100% reliable, but does the fd number fixed on most of the cases ?

[UPDATE]:

The reason why I don't parse the cmdline is because:

xb@dnxb:~/Downloads$ cat foo.sh 
#!/bin/bash
cat "/proc/$$/cmdline" | tr '\0' '\n'
readlink -f /proc/$$/fd/255

xb@dnxb:~/Downloads$ bash --norc foo.sh --norc
bash
--norc
foo.sh
--norc
/home/xiaobai/Downloads/foo.sh
xb@dnxb:~/Downloads$ 

As you can see, only fd able to give the full path /home/xiaobai/Downloads/foo.sh, but not the cmdline. And the script can't distinguish either foo.sh or --norc is a path or an option since foo.sh can appear at any option position, unless I do ugly checking such as it's not startswith --.

While fd has no problem to produces the correct full path even I do bash --norc foo.sh --norc foo2.sh.

Anyway, I just realized my task don't have to check this since I noticed no system processes except custom process are inherited from shell. But still any answer will help to future reader.

  • Relating: unix.stackexchange.com/a/377514/117549 – Jeff Schaller Jan 19 '18 at 16:23
  • Rather than describing your approach to answering your own question, I suggest that you edit the question to tell is what you're trying to accomplish. I don't understand how "full path executed from any shell process" has anything to do with open files. – Andy Dalton Jan 19 '18 at 21:19
  • @AndyDalton I learn this trick from this answer: stackoverflow.com/a/16131743/1074998 . What I want to do is get the path (and also executed path if it's shell) of all running process pid and then use dpkg-query to print the package description, manual, filetype into single file. I just done similar concept for a specific directory at github.com/limkokhole/binaries_brief, but now I want to apply it on all running processes too. – 林果皞 Jan 19 '18 at 22:10
  • If you want the path of the process, couldn't you look at /proc/<pid>/cmdline? – Andy Dalton Jan 19 '18 at 22:21
  • @AndyDalton But I have no way to distiguish between parameters with executing path from cmdline. And I figure out fd example can get the path, i.e. /tmp/a.sh – 林果皞 Jan 19 '18 at 22:23
0

Expanding on my comment above, you might be able to use /proc/<pid>/cmdline to get the information in which you're interested. Note that the tokens are NIL-character delimited, so you'll have to process the output a bit:

cat /proc/<pid>/cmdline | tr "\0" " "

So, if for instance I have:

$ cat foo.sh
#!/bin/bash
echo $(cat "/proc/$$/cmdline" | tr "\0" " ")

Here are some sample runs:

$ bash foo.sh
bash foo.sh

$ ./foo.sh
/bin/bash ./foo.sh

$ ./foo.sh 1 2 3 4
/bin/bash ./foo.sh 1 2 3 4

Note that that doesn't always get you the full path to the binary. For that, you could look at /proc/<pid/exe:

$ ls -l /proc/$$/exe
... /proc/12345/exe -> /bin/bash

That may not be what you're after, I just don't understand how looking at the open file descriptors is going to give you what you want.

  • Hi, I just tested and noticed it still same problem from what I worry, e.g.: bash --norc foo.sh, the executing path foo.sh do not appear on the 1st parameter and no way to know which one is the path (Unless I check it startswith -, but I'm not sure is portable for all shells or not, which some shells may allow option without -). Second thing is, the path is not a full path (I know exe will shows /bin/bash, but what I worry is foo.sh is not a absolute path). – 林果皞 Jan 20 '18 at 13:39
  • I just do a quick check with ps auxfww, I noticed I don't have to worry it, since there are no system processes(excluded my custom script) inherited from shell. But still if someone can give a solution it may helpful to future reader. – 林果皞 Jan 20 '18 at 13:43
  • the executing path foo.sh do not appear on the 1st parameter then it's relative to the working dir of the process (/proc/{id}/cwd) that you can use as a prefix to the shell script. – xenoid Jan 24 '18 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.