2

So I've got a .bash_aliases file with many exported bash functions inside; a good deal of which are incompatible with sh...

The problem is that sh is used all over my laptop (OS X) and linux machines that I ssh into. In addition it always tries to import my bash functions and spams errors.

The functions in question are:

  • all of my functions that have a '-' in their name (NOTE: these only spam errors on OS X, not linux)
  • and a log() function (below) with syntax that is only legal in bash

    log() {
        # braces allow for piping of same output to multiple files
        { $@ 2> >(tee .err.log); } &> >(tee .out.log);
        echo; echo logged output to .err.log \& .out.log respectively;
    }
    export -f log
    

So how can I solve this problem? I'd prefer it if I didn't have to rename the functions or put them in separate scripts inside a */bin directory...

Thanks for the help!

P.S. screenshot:

enter image description here

EDIT: I see I didn't include enough info. So yes .bash_profile does source .bashrc which in turn sources .bash_aliases (I have no .profile). In addition I have already tried to create an exit clause in .bash_aliases when $SHELL='sh' but it didn't work which is because they are being imported directly from my environment (as @Bodo and the import errors in screen cap indicate).

EDIT2 IMPORTANT: Also strangely I just found out that in the linux machine that I ssh into /bin/sh is a symbolic link to bash. Which means that bash although throwing no errors when sourcing log() actually does throw errors when importing it from the environment??

terdon
  • 234,489
  • 66
  • 447
  • 667
profPlum
  • 125
  • 5
  • `.bash_aliases` isn't a standard file. Where are you sourcing it from? Ubuntu sources it in `.bashrc`, are you doing that? And does your `.profile` also source `.bashrc`? – terdon Jun 14 '19 at 15:47
  • I don't know what you mean about it not being 'standard' because many auto-generated `.bashrc` files I've seen source it. Also yes, both my `.bash_profile` and my `.bashrc` do that. – profPlum Jun 14 '19 at 15:49
  • Just find where it's sourced and comment it out. `grep -R .bash_aliases ~/` – deimos Jun 14 '19 at 15:55
  • @profPlum "not standard" means that it isn't part of the bash setup. Some systems modify their default bashrc files to source it, but that's up to each individual distribution. I haven't seen it outside Ubuntu, but it might be a Debian thing too. But it certainly isn't a bash thing, so it's easy to avoid. – terdon Jun 14 '19 at 15:57
  • Wait, does your `~/.profile` do it too or only your `~/.bash_profile`? And what operating systems are you using? Is their `/bin/sh` actually `sh` or is it a symlink to `/bin/bash` or `/bin/dash` or something else? – terdon Jun 14 '19 at 16:06
  • Also, are you actually _exporting_ the functions? Do you have `export -f functionName` in the file? – terdon Jun 14 '19 at 16:08
  • @terdon: Yes I am exporting them, but no I have no `.profile` I have found that a `.profile` is unnecessary (i've only ever use `.bash_profile`). Also my OS is OSX (mojave) and I ssh into linux machines – profPlum Jun 14 '19 at 16:32
  • Why do you export them? Does not exporting solve the issue? I doubt it since they wouldn't be exported to an ssh session anyway. More importantly, what is `/bin/sh` on the machines that complain? Is it a symlink to `/bin/bash` perhaps? Can you give us a specific example that can reproduce the error? I am now unclear on if you get these errors when sshing or on your local macOS machine. – terdon Jun 14 '19 at 16:36
  • When bash is called as `sh`, it behaves like an actual `sh` (sorta, it's in what's known as POSIX mode). Many systems have `/bin/sh` as a symlink to `/bin/bash`, which means it cannot deal with `-` in function names. That's why I think my answer with `$BASH_VERSION` should fix it. – terdon Jun 14 '19 at 16:53
  • @terdon: First, see my edits. Also I export them because I believed that that is necessary to use them outside of the file they are defined in. Is that not true? Lastly: that's good to know but doesn't change the fact that the errors are for *importing* the functions (i.e. not for sourcing them) – profPlum Jun 14 '19 at 16:55

2 Answers2

2

The simple solution is to not source them. Since ~/.bash_aliases isn't a standard file, you must be explicitly sourcing it in one of your config files. So an easy solution would be to find the line that source it (most likely in your ~/.bashrc) and change it from this (or whatever your system has, this one is from Ubuntu):

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

To this:

if [ -f ~/.bash_aliases ] && [ -n "$BASH_VERSION" ]; then
    . ~/.bash_aliases
fi

That way, the .bash_aliases file will only be sourced when running bash.


To clarify, what I am assuming is happening here based on the information in your question and comments, is the following:

  1. You are sshing into a machine.

  2. Because you are sshing into it, this launches the default /bin/sh as a login shell.

  3. Since this is a login shell, it will source ~/.profile.

  4. Because your .profile is set up to source ~/.bashrc (again, not standard, but common), you now read .bashrc although you might not be running bash.

  5. Since your .bashrc is set up to source ~/.bash_aliases, you read that file too and that produces the errors.

Yet another reason why I personally am not a fan of the decision some systems have made to make the default ~/.bashrc source ~/.profile.

terdon
  • 234,489
  • 66
  • 447
  • 667
  • Probably `/bin/sh` does not source `.bash_aliases`, but the exported function is passed to `sh`, see https://unix.stackexchange.com/q/157547/330217 – Bodo Jun 14 '19 at 15:58
  • @Bodo I don't see the relevance. sh is sourcing `.bash_aliases` because the OP is logging into a remote machine, so starting a login shell. Login shells read `.profile` and the OP's `.profile` is set to source `.bashrc` which, in turn, sources `.bash_aliases` :) – terdon Jun 14 '19 at 16:01
  • @Bodo see updated answer, I explained it a bit more. – terdon Jun 14 '19 at 16:05
  • The OP wrote explicitly about "exported functions". I may have overlooked it, but where did you find the information that `.profile` sources `.bashrc`? – Bodo Jun 14 '19 at 16:06
  • @Bodo yeah, I am sort of assuming that the functions aren't actually exported since the question doesn't show any `export -f`. I took that to be a misunderstanding of the OP's. The rest I got because we know the OP is running a login shell and yet stuff defined in bashrc is being called and [from this comment](https://unix.stackexchange.com/questions/524928/how-to-squelch-sh-errors-from-imported-bash-functions/524931?noredirect=1#comment970964_524928). – terdon Jun 14 '19 at 16:07
  • @terdon: I'm sorry I forgot to mention I already tried something like this. specifically I tried: `if [ $SHELL='sh' ]; then exit 0; fi` inside my .bash_aliases script. It didn't work and I assumed this was because sh was directly importing the files *from my environment*. – profPlum Jun 14 '19 at 16:21
  • @terdon: they are indeed being exported, I didn't include the `export -f log` because it wasn't part of the `log()` source code technically... @Bodo: also in essence I believe you are correct – profPlum Jun 14 '19 at 16:29
  • @profPlum your `[ if $SHELL ]` won't help. The `$SHELL` variable just has your default login shell, it doesn't have any relation to the shell you are currently running. Actually, this would be much easier to sort out if we could have a quick chat so you can show the relevant files. If you have the time, please give me a ping (`@terdon`) here: https://chat.stackexchange.com/rooms/94923/discussion-on-question-524928 – terdon Jun 14 '19 at 16:47
2

You should not export the functions. Instead I suggest to source .bash_aliases for all bash instances that need it. (I guess you need the functions in interactive bash shells only.)

A similar problem is mentioned here: /bin/sh: error importing function definition for `some-function', where the accepted answer proposes to rename the functions.

You see the errors even if /bin/sh is linked to bash on your system, because when bash is called as sh, it tries to behave like sh and to comply with POSIX, see https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-with-name-sh

Bodo
  • 5,979
  • 16
  • 27
  • correct me if I'm wrong but won't just sourcing the file not bring the functions into the env of the bash shell that sourced it? Your right I only need it for interactive bash (and possibly some of my scripts) but I was under the impression that they needed to be exported to be used interactively? – profPlum Jun 14 '19 at 16:19
  • @profPlum no, not at all. You only need to export them if you will need them in child shells launched by your main one. Does not exporting solve it? Kudos to Bodo, if so, but that's really surprising since exported functions won't be carried over to the remote shell you ssh into. – terdon Jun 14 '19 at 16:38
  • @terdon: I have the roughly the same setup on both machines (similar `.bashrc` and same `.bash_aliases`). So that is why they 'carry'. Also that is good to know, I will try that now and see what happens. – profPlum Jun 14 '19 at 16:57
  • @profPlum to assuage my curiosity, could you give an example of when this was happening? I can't reproduce through ssh. Did you only see these messages on your local machine or when running a script? – terdon Jun 14 '19 at 17:05
  • Bodo: thanks that worked! didn't know I didn't need to export :) @terdon: also thanks for your help & extra effort, I would upvote you but I don't have the reputation to do it. If I get that rep soon I will. Both of you have a good day! :) – profPlum Jun 14 '19 at 17:06