2

Is it possible to "listen" to a variable's value during the start of a new shell?

I have a script that checks for the $PATH variable in the typical places, but I'd like to try something different. Here's what I'm thinking:

Instead of just guessing at where $PATH is set, I'd like to spawn a new shell for the user in the background, by running a command called something like "path-inspector". path-inspector spawns a new shell for the current user and listens to the $PATH variable. Maybe it sets $PATH to an empty string first, but anytime $PATH is modified, the command echo's out the filename with line number that modified $PATH. It would be like setting breakpoints and having a debugger specifically for $PATH.

I still feel like I'm in the stage where I don't know have a clear picture of how this could be implemented. Here's what I'm aware of that I'd need to address:

  • Subshells can't export variables back to the parent so I would need to devise an approach to echo'ing or reporting the results.
  • I don't know of any builtin that "listens to" a variable, so I'd need an approach to this as well. Possibly injecting a command before and/or after each command in the new shell is run to echo or tee the output?
  • Environmental variables aren't just these big global things, they are created for each shell, and more specifically, for each process. They'll be similar, but I'd need to at least be aware that, for example, a non-interactive shell might not have the same $PATH as a login shell. So if the command creates a "subshell", it may or may not use the same settings as a normal login shell.
  • Different shells. bash, sh, zsh, fish, etc.

I'm open to feedback of any kind: "Its already been done", "It's not possible", or "you'd also need to know about this". etc.

2
  • Are we talking Linux here? If so, have you thought of using /proc/PID/environ? Commented Apr 24, 2014 at 13:04
  • most commonly osx, though I'd like to support both. I'm not familiar with proc. Can you expand on /prod/PID/environ?
    – brock
    Commented Apr 24, 2014 at 14:11

1 Answer 1

0

ksh actually implements a neat feature called discipline functions which basically allows you to attach callbacks to setting or referencing a variable:

$ cat t.sh
#!/bin/ksh

PATH=

function PATH.set
{
    echo "new PATH in ${.sh.file}:${.sh.lineno}:"
    echo "  old = [${PATH}]"
    echo "  new = [${.sh.value}]"
}

PATH=/bin:/usr/bin:/sbin:/usr/sbin
PATH=$PATH:$PATH

.

$ ./t.sh
new PATH in t.sh:12:
  old = []
  new = [/bin:/usr/bin:/sbin:/usr/sbin]
new PATH in t.sh:13:
  old = [/bin:/usr/bin:/sbin:/usr/sbin]
  new = [/bin:/usr/bin:/sbin:/usr/sbin:/bin:/usr/bin:/sbin:/usr/sbin]

Similarly, PATH.get would be executed everytime $PATH is referenced.

Unfortunately, as it seems you cannot export functions in ksh93, this would restrict the callback to the current script limiting its overall usefulness.

2
  • Very cool feature. I tested it out and found that if you use ${.sh.value} inside the function it shows what the value is being changed to, so I made an edit to your answer. Will definitely play around with this and see if it can accomplish what I need.
    – brock
    Commented Apr 24, 2014 at 14:24
  • @brockangelo Good catch, fixed the typo :-) Commented Apr 24, 2014 at 14:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .