ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Is anyone here familiar with the internals of Bash? I want to hack at it some and change how the shell searches for executable commands in PATH. The goal is to make a flag in PATH (or perhaps a new env. variable altogether) that contains a list of directories. Executables would be found in each path entry such as:
path_entry1/*/bin
path_entry1/*/sbin
path_entry2/*/bin
path_entry2/*/sbin
etc.
The reason is this: I'm building a new LFS system and I really dislike the "put everything in /bin, /usr/bin/, /usr/local/bin, etc." mentality. I want each software package to reside in it's own directory (e.g. samba would be installed in /usr/local/packages/samba-X.Y/{bin,sbin,etc,var,share}).
Yes, I know this is not Unix-like, but that's why it's Linux From Scratch, right?
Yes, I know there will be other issues to deal with given this organization.
Yes, yes, yes, I have thought about it a great deal and want to try.
I've pulled up the bash source and have found the section of the code that does the hash searching. I don't imagine it will be too difficult to locate where the hash table is populated. I'm looking for anyone that has experience poking around in Bash that can point out any pitfalls or suggest files/line numbers to look at, or explain some of the internals.
Actually, what you want to do is exactly the Unix way, but not the 'usual' linux way.
What you want to do has been allowed for by the creation of the /opt directory where you can install each program in its' own folder and arrange things inside the folder any way you want.
BASH already does what you want by using wild-card expansion. After installing programs under /opt/progname/bin, just do this:
That's interesting. I'll admit, I never tried that because I had never seen it used before. Also, this LFS page (section 6.3.2.2) led me to believe that wildcards/globbing would not work in environment variables (namely PATH).
It raises some interesting questions, such as when does the wildcard expansion occur? at initial login? Each time a command is searched for?
I'll definitely give it a shot next time I sit down at my box. Thanks.
Oh those are good questions indeed. While writing, I was going to say that it might work. Then I thought I'd see, so I created a fake prog called
/opt/test/test
and did a 'which test' and got /opt/test/test
Perhaps this doesn't work with 'env', but it seems to be fine for BASH itself.
Any ideas on why this isn't working? Maybe something added/changed in each of your distributions? I've still got a bare-minimum install of LFS at this point.
Last edited by Dark_Helmet; 02-14-2007 at 02:27 AM.
Try declaring the PATH and exporting separately:
PATH=/bin:/usr/bin:/packages/installed/*/bin
export PATH
Also try enclosing in quotes:
PATH="/bin:/usr/bin:/packages/installed/*/bin"
export PATH
Dark_Helmet, that is very strange. On my CentOS box, the paths are being expanded when I assign them to the variable. Also, remember that paths should be delimited by a colon (':'). Have a look at this example:
I'm not sure what the hang-up is, but it's still there. I have another LFS system built with a previous release of LFS that does not exhibit the same behavior--it expands the wildcard.
So, for the moment, I'll chalk it up as a problem with a configuration file (or two) that I haven't set up yet.
If it's not a config file issue, I've figured a way around it (very similar to anomie's method). When I have more time, I'll experiment.
I'm not sure what the hang-up is, but it's still there. I have another LFS system built with a previous release of LFS that does not exhibit the same behavior--it expands the wildcard.
Bash does filename (wildcard) expansion on the string that is assigned to a variable, for example
Code:
export FOO=/opt/*/bin
It does not do filename expansion on colon-delimited elements of a such a string, such as
Code:
export FOO=/bin:/usr/bin:opt/*/bin
Nor does bash know to replace spaces with colons, which would also be necessary for this to have the desired result.
So, one solution is to use something like anomie's approach of assigning a single expandable string to one variable and then using it to help build PATH. Perhaps a simpler method would be to use process substitution each time a wild card is needed within the assignment to PATH, such as
This should work as long you haven't got colons in your directory names (but I'd have no idea how to get bash's PATH to properly understand those directories anyway). You could also do this using find in instead of perl.
@gnashley:
Yeah, I had originally tried quoting the string with the wildcard - no luck.
@matthewg42:
I had come across GoboLinux before, was interested by it, but lost the link. From their page, it sounds as if their solution is fairly complex. I'll look into it some more when I have time. Thanks for helping me find their website again.
@jr1:
I'm using a temporary method similar to what you provided at the moment. I'll give it a test drive and see how it works. Basically, in /etc/profile I have this:
Code:
for directory in $( ls -d /pkgs/inst/* ) ; do
if [ -d ${directory}/bin ] ; then
export PATH=${PATH}:${directory}/bin
fi
if [ -d ${directory}/sbin -a ${EUID} -eq 0 ] ; then
export PATH=${PATH}:${directory}/sbin
fi
...
done
There's a little more involved -- I handle other environment variables similarly (LD_LIBRARY_PATH, MANPATH, INFOPATH, PKG_CONFIG_PATH). I decided to go with this (for the moment) because te environment variable is a regular char *, meaning it can be arbitrary in length.
The primary drawback of this method is that it takes a re-login to "see" any packages installed while the user was logged in.
It also takes a little experimentation to get a package installed and live neatly in its own space, but that's expected.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.