Mac OSX n00b: what is a .login file? - macos

Firstly, I'm using Mac OS X. Secondly, I am attempting to install something which says:
If you include this line (or source $CALDB/software/tools/caldbinit.sh
for Bourne shell users) in your .login file, then the CALDB will be
available to you every time you log in.
What exactly is the .login file? And where can it be found?

On *nix systems, each time you login, it looks for a file named .login and executes any commands it finds in the file. Much like when you start a new C shell, the system looks for a file named .cshrc and executes it.
Though OSX uses other ways to implement this functionality, .login is still recognized. Typically .login file includes a command to "source" (read and execute) a standard system login file that sets the standard PATH, TERM, and PROMPT variables. Others such as your CALDB installation want to be initialized at login time by inserting the appropriate source line:
source $CALDB/software/tools/caldbinit.sh
Note you may have to substitute the literal path for $CALDB in the path above since that var may not be initialized at the time of login when this script is run.
Addendum:
.login is typically in the home directory when using csh or tsch shells. If it's not there, you'll have to create it. However, depending on the version of OSX you are using you may have other options or different ways of achieving the same effect. Follow the documentation (link provided above) for the best option for your version of OS X.

Related

in which order will ubuntu search bin-folders for executables?

So I learned that in order to be able to execute a program from everywhere in the shell I have to put a reference file looking something like
#!/bin/bash
path/to/my/original/executable
in my bin-directory and make it executable.
On my current linux system (provided by my workplace) there are multiple bin-directories like
/usr/local/bin
/home/MyUsername/bin/
/home/otherUsername/bin/
For my work I have to alter a c++ program which is supposed to be usable for every user on the computer (hence I used /usr/local/bin/ sofar). But I realized that my changes to the original program do not come through... So my questions are:
Where could other bin-folders be, that I need to check for old executables?
How does my operating system (ubuntu 16.04) choose between executables in different bin-locations but with the same name?
Thanks in advance!
The PATH shell variable contains a colon separated list of paths to look for executables in. The list is processed left to right, the shell executes the first executable binary it finds (make sure to chmod +x the binary you are providing). If you want an easier printout you can use: echo $PATH | tr ":" "\n". Also keep in mind that a program might have been started with a different PATH than your shell and that users can customize their PATH variable. Systemwide PATH settings can usually be found in /etc/profile or /etc/profile.d/. You can use which file to display the full path expansion of file.

What is the Bash file extension?

I have written a bash script in a text editor, what extension do I save my script as so it can run as a bash script? I've created a script that should in theory start an ssh server. I am wondering how to make the script execute once I click on it. I am running OS X 10.9.5.
Disagreeing with the other answers, there's a common convention to use a .sh extension for shell scripts -- but it's not a useful convention. It's better not to use an extension at all. The advantage of being able tell that foo.sh is a shell script because of its name is minimal, and you pay for it with a loss of flexibility.
To make a bash script executable, it needs to have a shebang line at the top:
#!/bin/bash
and use the chmod +x command so that the system recognizes it as an executable file. It then needs to be installed in one of the directories listed in your $PATH. If the script is called foo, you can then execute it from a shell prompt by typing foo. Or if it's in the current directory (common for temporary scripts), you can type ./foo.
Neither the shell nor the operating system pays any attention to the extension part of the file name. It's just part of the name. And by not giving it a special extension, you ensure that anyone (either a user or another script) that uses it doesn't have to care how it was implemented, whether it's a shell script (sh, bash, csh, or whatever), a Perl, Python, or Awk script, or a binary executable. The system is specifically designed so that either an interpreted script or a binary executable can be invoked without knowing or caring how it's implemented.
UNIX-like systems started out with a purely textual command-line interface. GUIs like KDE and Gnome were added later. In a GUI desktop system, you can typically run a program (again, whether it's a script or a binary executable) by, for example, double-clicking on an icon that refers to it. Typically this discards any output the program might print and doesn't let you pass command-line arguments; it's much less flexible than running it from a shell prompt. But for some programs (mostly GUI clients) it can be more convenient.
Shell scripting is best learned from the command line, not from a GUI.
(Some tools do pay attention to file extensions. For example, compilers typically use the extension to determine the language the code is written in: .c for C, .cpp for c++, etc. This convention doesn't apply to executable files.)
Keep in mind that UNIX (and UNIX-like systems) are not Windows. MS Windows generally uses a file's extension to determine how to open/execute it. Binary executables need to have a .exe extension. If you have a UNIX-like shell installed under Windows, you can configure Windows to recognize a .sh extension as a shell script, and use the shell to open it; Windows doesn't have the #! convention.
You don't need any extension (or you could choose an arbitrary one, but .sh is a useful convention).
You should start your script with #!/bin/bash (that first line is understood by execve(2) syscall), and you should make your file executable by chmod u+x. so if your script is in some file $HOME/somedir/somescriptname.sh you need to type once
chmod u+x $HOME/somedir/somescriptname.sh
in a terminal. See chmod(1) for the command and chmod(2) for the syscall.
Unless you are typing the whole file path, you should put that file in some directory mentioned in your PATH (see environ(7) & execvp(3)), which you might set permanently in your ~/.bashrc if your login shell is bash)
BTW, you could write your script in some other language, e.g. in Python by starting it with #!/usr/bin/python, or in Ocaml by starting it with #!/usr/bin/ocaml...
Executing your script by double-clicking (on what? you did not say!) is a desktop environment issue and could be desktop specific (might be different with
Kde, Mate, Gnome, .... or IceWM or RatPoison). Perhaps reading EWMH spec might help you getting a better picture.
Perhaps making your script executable with chmod might make it clickable on your desktop (apparently, Quartz on MacOSX). But then you probably should make it give some visual feedback.
And several computers don't have any desktop, including your own when you access it remotely with ssh.
I don't believe it is a good idea to run your shell script by clicking. You probably want to be able to give arguments to your shell script (and how would you do that by clicking?), and you should care about its output. If you are able to write a shell script, you are able to use an interactive shell in a terminal. That it the best and most natural way to use a script. Good interactive shells (e.g. zsh or fish or perhaps a recent bash) have delicious and configurable autocompletion facilities and you won't have to type a lot (learn to use the tab key of your keyboard). Also, scripts and programs are often parts of composite commands (pipelines, etc...).
PS. I'm using Unix since 1986, and Linux since 1993. I never started my own programs or scripts by clicking. Why should I?
just .sh.
Run the script like this:
./script.sh
EDIT: Like anubhava said, the extension doesn't really matter. But for organisational reasons, it is still recommended to use extensions.
I know this is quite old now but I feel like this adds to what the question was asking for.
If your on a mac and you want to be able to run a script by double clicking it you need to use the .command extension. Also same as before make file executable with chmod -x.
As was noted before, this isn't really that useful tbh.
TL;DR -- If the user (not necessarily the developer) of the script is using a GUI interface, it depends on what file browser they are using. MacOS's Finder will require the .sh extension in order to execute the script. Gnome Nautilus, however, recognizes properly shebanged scripts with or without the .sh extension.
I know it's already been said multiple times the reasons for and against using an extension on bash scripts, but not as much why or why not to use extensions, but I have what I consider to be a good rule of thumb.
If you're the type who hops in and out of bash and using the terminal in general or are developing a tool for someone else who does not use the terminal, put a .sh extension on your bash scripts. That way, users of that script have the option of double-clicking on that file in a GUI file browser to run the script.
If you're the type who primarily does all or most of your work in the terminal, don't bother putting any extension on your bash scripts. They would serve no purpose in the terminal, assuming that you've already set up your ~/.bashrc file to visually differentiate scripts from directories.
Edit:
In the Gnome Nautilus file browser with 4 test files (each with permissions given for the file to be executed) with stupidly simple bash command to open a terminal window (gnome-terminal):
A file with NO extension with #!/bin/bash on the first line.
It worked by double-clicking on the file.
A file with a .sh extension with #!/bin/bash on the first line.
It worked by double-clicking on the file.
A file with NO extension with NO #!/bin/bash on the first line.
It worked by double-clicking on the file...technically, but the GUI gave no indication that it was a shell script. It said it was just a plain text file.
A file with a .sh extension with NO #!/bin/bash on the first line.
It worked by double-clicking on the file.
However, as Keith Thompson, in the comments of this answer, wisely pointed out, relying on the using the .sh extension instead of the bash shebang on the first line of the file (#!/bin/bash) it could cause problems.
Another however, I recall when I was previously using MacOS, that even properly shebanged (is that a word?) bash scripts without a .sh extension could not be run from the GUI on MacOS. I would love for someone to correct me on that in the comments though. If this is true, it would prove that there is a least one file browser out there where the .sh extension matters.

Emacs adding (prepending) ".:" to PATH in shell

I have noticed that my shell buffers in Emacs (24.3.1) have (an extra) ".:" at the beginning of the $PATH variable on my Mac OS X (but not on my linux laptop that has the same . files), compared to my regular shell, which has it in the middle somewhere. Is this just me, or does Emacs on mac do this for some purpose? And can I prevent it? I don't think it has caused any actual problems, but it does cause warnings from RVM, and theoretically it has risks.
Thanks!
According to the emacs help entry for the shell command, the started shell gets the file ~/.emacs_SHELLNAME or ~/.emacs.d/init_SHELLNAME.sh as first command list (if one of those files exist). So you can modify the value of the PATH environment variable in one of those two files, but you should then check that your shell (configurable with the explicit-shell-file-name variable, the ESHELL environment variable or the shell-file-name variable, in that order) does not ignore commands that are issued during start-up.
Another reason may be that your (system-wide) configuration includes the current directory into the PATH value (you can check that with echo $PATH in a terminal), thus you would have to reconfigure your shell instead of emacs.
Considering security, having the current directory in the PATH does have the risk of unintentionally executing the wrong program (eg.: you have a self-written program named test and want to execute /usr/bin/test). That may cause some serious trouble, if that happens while working with super-user privileges.

How to set the $PATH as used by applications in os x

I'm using ant to build my project, and use the 'svnversion' executable to insert a version id into my sources for easy tracking of versions.
Running this ant file from the command line works, I've set my $PATH in .profile to include the path to svnversion and it works fine.
Now I try and run this same ant file from inside Eclipse and that does not work - the PATH in eclipse is set in another way than the PATH of the shell, I suspect this has to be set in a plist somewhere, but I don't know where.
Correct -- it's in the plist file
~/.MacOSX/environment.plist
This file actually contains key-value pairs for any environment variables you want to set, for the whole login session. Unlike .profile/.cshrc etc, it's available to GUI programs. Unfortunately, you can't access other environment variables (e.g., you can't use $HOME) or use any other programmatic constructs here.
Update: note that this is no longer supported under OS X 10.8 Mountain Lion, alas.
A quick search at developer.apple.com turned up Setting environment variables for user processes.
On Mac OS X El Capitan (10.11.5), this works for me for per-user PATH entries (and other environment variables, for that matter).
create a file $HOME/.profile
set all PATH related variables in that file
(if using bash), have your .bash_profile source that file, and .bashrc. This should be the entire contents of your .bash_profile:
# $HOME.bash_profile:
source $HOME/.profile
source $HOME/.bashrc
Near as I can tell, Mac OS does not source .bash_profile on login for PATH, presumably because that is often very slow to run (initializing bash completion etc). It does seem to read $HOME/.profile.
You still need a $HOME/.bash_profile to trigger bash to read $HOME/.bashrc, which it otherwise wouldn't do for interactive, non-login terminals as the ones created by Terminal.app.

What's the difference between .bashrc, .bash_profile, and .environment?

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I've used a number of different *nix-based systems of the years, and it seems like every flavor of Bash I use has a different algorithm for deciding which startup scripts to run. For the purposes of tasks like setting up environment variables and aliases and printing startup messages (e.g. MOTDs), which startup script is the appropriate place to do these?
What's the difference between putting things in .bashrc, .bash_profile, and .environment? I've also seen other files such as .login, .bash_login, and .profile; are these ever relevant? What are the differences in which ones get run when logging in physically, logging in remotely via ssh, and opening a new terminal window? Are there any significant differences across platforms (including Mac OS X (and its Terminal.app) and Cygwin Bash)?
The main difference with shell config files is that some are only read by "login" shells (eg. when you login from another host, or login at the text console of a local unix machine). these are the ones called, say, .login or .profile or .zlogin (depending on which shell you're using).
Then you have config files that are read by "interactive" shells (as in, ones connected to a terminal (or pseudo-terminal in the case of, say, a terminal emulator running under a windowing system). these are the ones with names like .bashrc, .tcshrc, .zshrc, etc.
bash complicates this in that .bashrc is only read by a shell that's both interactive and non-login, so you'll find most people end up telling their .bash_profile to also read .bashrc with something like
[[ -r ~/.bashrc ]] && . ~/.bashrc
Other shells behave differently - eg with zsh, .zshrc is always read for an interactive shell, whether it's a login one or not.
The manual page for bash explains the circumstances under which each file is read. Yes, behaviour is generally consistent between machines.
.profile is simply the login script filename originally used by /bin/sh. bash, being generally backwards-compatible with /bin/sh, will read .profile if one exists.
That's simple. It's explained in man bash:
/bin/bash
The bash executable
/etc/profile
The systemwide initialization file, executed for login shells
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
~/.bash_logout
The individual login shell cleanup file, executed when a login shell exits
~/.inputrc
Individual readline initialization file
Login shells are the ones that are read one you login (so, they are not executed when merely starting up xterm, for example). There are other ways to login. For example using an X display manager. Those have other ways to read and export environment variables at login time.
Also read the INVOCATION chapter in the manual. It says "The following paragraphs describe how bash executes its startup files.", i think that's a spot-on :) It explains what an "interactive" shell is too.
Bash does not know about .environment. I suspect that's a file of your distribution, to set environment variables independent of the shell that you drive.
Classically, ~/.profile is used by Bourne Shell, and is probably supported by Bash as a legacy measure. Again, ~/.login and ~/.cshrc were used by C Shell - I'm not sure that Bash uses them at all.
The ~/.bash_profile would be used once, at login. The ~/.bashrc script is read every time a shell is started. This is analogous to /.cshrc for C Shell.
One consequence is that stuff in ~/.bashrc should be as lightweight (minimal) as possible to reduce the overhead when starting a non-login shell.
I believe the ~/.environment file is a compatibility file for Korn Shell.
I found information about .bashrc and .bash_profile here to sum it up:
.bash_profile is executed when you
login. Stuff you put in there might be
your PATH and other important
environment variables.
.bashrc is used for non login shells.
I'm not sure what that means. I know
that RedHat
executes it everytime you start
another shell (su to this user or
simply calling bash again) You might
want to put aliases in there but again
I am not sure what that means. I
simply ignore it myself.
.profile is the equivalent of
.bash_profile for the root. I think
the name is changed to let other
shells (csh, sh, tcsh) use it as well.
(you don't need one as a user)
There is also .bash_logout wich
executes at, yeah good guess...logout.
You might want to stop deamons or even
make a little housekeeping . You can
also add "clear" there if you want to
clear the screen when you log out.
Also there is a complete follow up on each of the configurations files here
These are probably even distro.-dependant, not all distros choose to have each configuraton with them and some have even more. But when they have the same name, they usualy include the same content.
According to Josh Staiger, Mac OS X's Terminal.app actually runs a login shell rather than a non-login shell by default for each new terminal window, calling .bash_profile instead of .bashrc.
He recommends:
Most of the time you don’t want to maintain two separate config files
for login and non-login shells — when you set a PATH, you want it to
apply to both. You can fix this by sourcing .bashrc from your
.bash_profile file, then putting PATH and common settings in .bashrc.
To do this, add the following lines to .bash_profile:
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
Now when you login to your
machine from a console .bashrc will be called.
A good place to look at is the man page of bash. Here's an online version. Look for "INVOCATION" section.
I have used Debian-family distros which appear to execute .profile, but not .bash_profile,
whereas RHEL derivatives execute .bash_profile before .profile.
It seems to be a mess when you have to set up environment variables to work in any Linux OS.

Resources