Well, it depends on what you mean by "file" and how exactly the library accesses it. Here are a few approaches (both kluges) that come to mind:
- Use a temporary file, in the normal
mkstemp
meaning. mkstemp
returns a file descriptor number to an unlinked file. You can then create $FOO/mypasswd
as a symlink to /proc/self/fd/returned_number
. There is a small window where the file exists (between open and unlink), and something else running as the same user could open it, and hold the file descriptor to later read the password. You can be sure it'll not be written to disk if your temporary directory is on a tmpfs.
- If it doesn't need to
seek
the password file, use pipe
/pipe2
to create your file descriptors, then proceed as above with the symlink. You'll need to fork a child process to handle feeding the password to the pipe.
- You can probably abuse FUSE to do this.
- You could use
LD_PRELOAD
(or other dynamic linker tricks) to "fix" the library by intercepting the open
/read
/close
, and feed it the password from somewhere sane.
None of these are really secure from other processes. Other processes running as the same user could, for example, ptrace
your process and read the password directly out of memory.
As others have said, there isn't any way to wait on "not" a process ID. However this pattern of code doesn't seem that bad to me, so I offer it as a suggested way of achieving what you're after.
It makes use of Bash arrays which you can then give as a list to the wait
command.
Example
A modified version of your example code, cmd.bash
.
!/bin/bash
array[0]=1
array[0]=2
sleep 30 &
pid=$!
pidArr=()
for i in ${array[@]}; do
for n in $(seq 3); do
if [ $n -eq 1 ]; then
sleep 31 > file &
pidArr+=($!)
else
sleep 32 >> file &
pidArr+=($!)
fi
done
done
echo ${pidArr[@]}
I've substituted sleep
commands in this example just to simulate some long running jobs that we can background. They have nothing to do with this other than to act as stand-ins.
Also the final echo
command is there purely so we can see what happens when the for loops complete. Ultimately we'll replace it with an actual wait
command, but let's not get ahead of ourselves.
Example run #1
So let's run our program and see what happens.
$ ./cmd.bash
24666 24667 24668
Now if we check ps
:
$ ps -eaf|grep sleep
saml 24664 1 0 22:28 pts/9 00:00:00 sleep 30
saml 24666 1 0 22:28 pts/9 00:00:00 sleep 31
saml 24667 1 0 22:28 pts/9 00:00:00 sleep 32
saml 24668 1 0 22:28 pts/9 00:00:00 sleep 32
If we wait a bit, these will ultimately finish. But this shows that if we add the process IDs to an array we can echo
them out afterwards.
Example #2
So let's change that echo
line out and swap in a wait
line now, something like this:
wait ${pidArr[@]}
Now when we run our modified version we see that it's waiting on ALL the process IDs:
$ ./cmd.bash
...after ~30 seconds passes
$
We get back our prompt. So we successfully waited for all the processes. A quick check of ps
:
$ ps -eaf|grep sleep
$
So it worked.
Best Answer
lslocks
, from the util-linux package, does exactly this.In the
MODE
column, processes waiting for a lock will be marked with a*
.