bash filename completion hangs because it is searching in unrelated directories for unrelated files - linux

When I type
(module load /scratch/userName/productName/modules/d
followed by a tab in order to get
(module load /scratch/userName/productName/modules/debug
bash hangs for some time and does not accept input.
If I use strace to debug this, I can see that bash is calling stat() on more than 5000 (unrelated) files in 800 (unrelated) directories.
Could anybody explain this to me? Or even better, explain how to tell bash to only search in the specified directory?
edit:
The modules directory exists and contains only two normal files (debug and release). All of the parent directories are normal directories.
edit:
I guess this has something to do with bash ability to forward filename completion to the client being used. In this case this is module but I've also seen it for git.

Somebody somewhere registered some bash function to perform filename completion for the client module. In order to disable this I added the following line into my ~/.bashrc:
complete -o default module
Thanks to
https://stackoverflow.com/users/3266847/benjamin-w
for the hint!

Related

tar exclude error-output on specific paths

Is it possible to ignore error-messages like: /etc/some-tool/some-log: file changed as we read it on the same way you can use exclude to exclude files?
I'm using tar to do system-backups, redirecting stdout and stderr into log-files. I Got some direcotires which contain log-files. Simply don't want to have the same error-lines (like shown above) every day in my result file.
So far couldn't find a command on man tar which could help me.
I wrote a script which analyzes the output log and decides if it's an error or not. Ignoring warnings on a global scope is not what I was looking for. Took me some time but it's the safest method imo.

Linux daemon: alternative to chdir("/")?

I have a program (Crafty chess) that works just fine when started from the console. For my application I have daemonized it. When daemonizing a process, one is supposed to change the working directory to "/" via chdir("/").
When I follow that advice, the program exits in some use cases because it doesn't have the proper permissions in "/". When I don't chdir, the program works, but just leaving out chdir is a crutch.
Is there a sound alternative to omitting chdir("/")?
It probably should not write to the current directory. It'd be better to write to some specific directory instead. Instead of cd'ing to /tmp and writing files to the current directory, write files to /tmp/whatever — i.e. always use absolute paths.
And on a related note, don't hardcode /tmp if you can avoid it. Make it a configuration option, or use the $TMPDIR environment variable, or best of all, use mktemp().
You can call the daemon(3) function (with a non-zero first nochdir argument) so that it daemonize a process without doing the chdir("/"))
But as John Kugelman suggests, you should not write (nor read) any relative path in a daemonized program (or you should do an explicit chdir to a directory that you can read and write and search).

SVN Pre-commit Symbolic Link Path in Perl

In my workplace, there's one Perl script that runs on a Unix machine every time someone tries to check-in a file to the SVN repo for any of the 10-20 projects.
The way it works is that each project has its own "Hooks" folder with a file called "pre-commit" which SVN automatically executes when someone check-in something. Except the "pre-commit" file is actually a symbolic link to the one central Perl script common to all projects just so that if a change needs to be made to the Perl script it doesn't need to be done for every project.
So my problem is this: I need to put a text file in each of these projects' "hooks" directory, each one containing some settings specific to that project. So there will be 10-20 settings files (one per project) each in their respective "hooks" directory.
The problem is that I need to open these text files in the Perl script and read from them but I'm having issues letting Perl know where to find it. I tried using the $0 parameter which is supposed to tell me where the script is being executed from but because it's a symbolic link it just says "Not a directory" and the script terminates. I need to get the path of the "hooks" directory so that I can find the text file.
The SVN pre-commit script is supposed to be invoked with the path to the repository as its first argument. Inside a Perl script, that argument should be available as $ARGV[0]. You should be able to build the path to the corresponding hooks directory or to a file inside that directory by simply appending to the repository path, like this:
$repopath = $ARGV[0];
$hookspath = $repopath . "/hooks";
$myfilepath = $hookspath . "/myfile";
although for maximum portability it would be cleaner to use the pathname-manipulation functions in the File::Spec module to do this.
If this approach doesn't work then you'll have to explain more about how your Perl script gets invoked. For instance, if your pre-commit script is really a shell script wrapper that eventually invokes perl then perhaps it's not passing the pre-commit arguments along properly.
Showing us your current code that's failing would be a good thing too.

How to get external merge tools to work with svn on linux?

How do I get a GUI-based merge tool to work with command line SVN in linux? I understand that there are many options like meld, svn Diff, etc. out there. All of them require a helper script to allow svn to invoke the external program during conflict resolution. I followed the instructions given here and the nice svn manual with meld.
But in all cases, when I get to the merge conflict and type 'l' to invoke the external tool, I get an error: The external merge tool exited with exit code 255
I'm fairly certain I'm missing some key thing here. ITs too much of a coincidence for so many different solutions to fail. Would appreciate any solution or pointers to the problem.
Thanks!
Also make sure that the path in your config is absolute. It should be the same path you see when you run a pwd command from that directory. No aliases or relative paths. So if your username is foo you would replace this line:
Add this below it:
merge-tool-cmd = ~/bin/svn-merge-meld
With
Add this below it:
merge-tool-cmd = /Users/foo/bin/svn-merge-meld
You may not have the correct permissions on the wrapper script. Try something like this:
sudo chmod +x /usr/local/bin/mergewrap.py
I've found several wrapper scripts for vimdiff or meld which seem to pass the wrong number of arguments. Unless I've misunderstood the rather terse documentation about the commandline parameters, they only take 2 or 3 filenames. This may also cause the script to fail with an error.

Setting bash command-line variable to start my application

I'm pretty new to programming for Linux environments, so I don't exactly know what to search for in order to answer this question for myself. I need to understand how applications set the shell to accept a certain command to start them. For example, you can start Firefox from the command line by executing the command: firefox.
I don't know where this is defined. Makefile? Configure script? In the source code itself?
Any resources / reading on Linux programming tidbits like these would be greatly appreciated!
Thank you.
Firefox is launched by the command "firefox" because there is an executable file in one of the folders in the $PATH environment variable called "firefox".
Are you talking about the PATH variable? It seems like you are.
In linux, you should be able to type: "echo $PATH" (without quotes) and get a ":"-separated list of locations where programs are located (like firefox).
If you need to add something to your path, you should be able to do:
export PATH=$PATH:/another/directory
In your shell (which is most likely bash)
You can also type:
which firefox
To display the location of the firefox executable.
Typically the shell is going to have an environment variable called $PATH set. This is just an ordered list of all the directories to look when somebody types in a command. As soon as it finds an executable file (by which I mean a file for which you have execute permissions, not a file ending in .exe) with the same name as whatever was typed, it will run that file. Common directories in $PATH might be /bin, /usr/local/bin, ~/bin, etc.
So, when you type 'firefox', the shell looks through all the directories in $PATH until it finds /usr/local/bin/firefox, which it then runs. To make your own programs run the same way, you'll either need to put them (or a symbolic link to them) in a directory that is likely to be in every user's path (/usr/local/bin/ is a good choice), or you'll need to get your users to add your program's directory to their $PATH.
For a more complete description, see the Wikipedia article about the $PATH variable.
As an alternative to the modification of $PATH mentioned earlier, you could also copy or link your executable in one of the directories already in your $PATH. more specifically, /usr/local/bin/ is available on most UNIX system for pretty much this purpose (installing software outside the default package management of the operating system).
It has to be in the path as everyone else mentioned, but you might also need to make it executable with something like this:
chmod +x /path/to/file
And if it's a script there's usually a shebang at the top that tells the os what to use to execute it:
#! /usr/bin/python
Often, large packages are installed in /opt with a wrapper script or link somewhere in the PATH. For example, on my system, Google Picasa is installed in /opt/google/picasa and there is a symlink at /usr/bin/picasa to /opt/google/picasa/3.0/picasa
Firefox is at /usr/bin/firefox on my system and that's a symlink to /usr/bin/firefox-3.0 which is itself a symlink to /usr/lib/firefox-3.0.11/firefox.sh - That shell file fumbles around until it finally runs /usr/lib/firefox-3.0.11/firefox (unless it finds a reason to do something else). That, finally, is a binary executable. So /usr/lib is where firefox is installed, for me.
You can use this command to find out where a program is:
type -a firefox
Then, you can find out what kind of file it is using this:
file /usr/bin/firefox
Also see the Filesystem Heirarchy Standard for more information about recommended locations for files and programs.

Resources