emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* How to get shell source blocks to read my profile?
@ 2021-03-14 21:30 George Mauer
  2021-03-14 21:51 ` Tim Cross
  0 siblings, 1 reply; 12+ messages in thread
From: George Mauer @ 2021-03-14 21:30 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1248 bytes --]

I am confused why no matter how I try to run shell commands they seem to be
missing variables exported in profiles.

I have added 3 variables to various startup scripts

  - ~./bash-profile~ :: ~export GIM_BASH_PROFILE="yes"~
  - ~./bashrc~ :: ~export GIM_BASHRC="yes"~
  - ~./zshrc~ :: ~export GIM_ZSHRC="yes"~

I am running emacs in GUI mode so I get why none of these are available
*directly* in emacs, so then I try

  #+begin_src shell :results list
    env | grep GIM
  #+end_src

  #+RESULTS:

Ok that's kinda surprising, but I suppose it could be running ~/bin/zsh~
(that's my ~shell-file-name~) directly

what about

  #+begin_src shell :results list
    bash -c env | grep GIM
  #+end_src

  #+RESULTS:

That's pretty surprising. I would have expected running it directly to
actually run my profile.

Shockingly

  #+begin_src shell :results list
    bash --rcfile ~/.bashrc -c env | grep GIM
  #+end_src

  #+RESULTS:

That is *still* nothing!

Sanity is restored slightly when I run

  #+begin_src shell :results list
    bash --login -c env | grep GIM
  #+end_src

which *does* indeed visit ~.bash_profile~ but only slightly.

What is going on, and is there a straightforward way in which I can get
shell block to read from a profile?

[-- Attachment #2: Type: text/html, Size: 1621 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-14 21:30 How to get shell source blocks to read my profile? George Mauer
@ 2021-03-14 21:51 ` Tim Cross
  2021-03-15  2:35   ` George Mauer
  0 siblings, 1 reply; 12+ messages in thread
From: Tim Cross @ 2021-03-14 21:51 UTC (permalink / raw)
  To: emacs-orgmode


Is this perhaps on a Mac where Emacs is started from the dock? If so, it
could be because on the mac, applications started from the dock are not
executed inside a login shell. Do you get different results if you start
emacs from within a terminal? If so, this is almost certainly the source
of your issue/difference.

I am also a little confused by your examples. Some of them are
attempting to source .bash_profile, others .bashrc and others .zshrc.
Which shell are you using and which files do you have? I get the feeling
that in your frustration, you have taken a 'shotgun' approach and added
the variable everywhere. It might be time to go back and look at all
your shell environment files and rationalise them a bit. Things can
become a little confusing when running zsh as so many things
assume/expect a bash shell. While zsh is pretty compatible with bash, so
few problems arise, it can lead to confusion regarding where to set
variables and understand what is being sourced and when.

For some reason, there seems to be some confusion these days about the
difference between .profile, .bash_profile, .bashrc, .zsh_profile and
.zshrc. In particular, I frequently see incorrect/wrong advice regarding
the use of 'profile' and 'rc' files. Most of it can
be blamed on wrong advice in forums like stack overflow!

The 'profile' and the 'rc' files fulfil different purposes and are
sourced at different times. Have a careful read of the bash man page
(even if your running zsh as they all tend to follow the same pattern).
I would also experiment with just dumping out the output of 'env' and
not run it through grep so that you can see what is being defined. This
can help you understand what is being sourced. I also think it is a good
idea to be explicit about the shell so that you have more
control/understanding over what is being run e.g. put the line

#!/bin/bash

or

#!/bin/zsh

or

#!/bin/sh

as the first line.

In very broad terms (glossing over some of the subtleties, which is
likely the cause of some of your issues), the 'profile' files are only
sourced for login shells and the 'rc' files are sourced whenever a new
shell process is run. Note that these processes run in a hierarchy i.e.
shell processes have a parent process. Some things have to be set in
your 'profile' (or are better set there) while other things must be set
in your 'rc' file. For example, setting PATH in your 'profile' is normal
because you typically just want that set once and then 'exported' to all
child processes. Setting a dynamic prompt which changes depending on the
directory your in (or because it has some other dynamic data, like the
time) need to be set in your 'rc' file because these are sourced before
each shell process is executed. I the 'old days' it was important to get
these distinctions correct because sourcing the files could have a
performance impact - not as big an issue these days.

These days, things seem to have become even more confusing in an attempt
to make things easier. I often see people with a .profile, a
.bash_profile, a .bashrc, a .zsh_profile and a .zshrc with variables set
and exported mixed in across all these files. This is a source of
terrible confusion and unexpected results. Some 'canned' shell
configurations, like 'oh-my-zsh' also try to be extra helpful by
sourcing files which are not normally sourced by that shell (to make
smoother migration from bash shells for example). Sometimes, it can be
helpful to put a line like the following into each of these files

echo "Executing <filename> at `date`" >> ~/profile.log

just to see what is getting executed when (you won't want to leave this
there - just for diagnostic and experimentation to help understand when
things are being sourced. You could even dump out the output of 'env' so
that you can see how the environment is being changed as each of these
files executes.


George Mauer <gmauer@gmail.com> writes:

> I am confused why no matter how I try to run shell commands they seem to be missing variables exported in profiles.
>
> I have added 3 variables to various startup scripts
>
>   - ~./bash-profile~ :: ~export GIM_BASH_PROFILE="yes"~
>   - ~./bashrc~ :: ~export GIM_BASHRC="yes"~
>   - ~./zshrc~ :: ~export GIM_ZSHRC="yes"~
>
> I am running emacs in GUI mode so I get why none of these are available *directly* in emacs, so then I try
>
>   #+begin_src shell :results list
>     env | grep GIM
>   #+end_src
>
>   #+RESULTS:
>
> Ok that's kinda surprising, but I suppose it could be running ~/bin/zsh~ (that's my ~shell-file-name~) directly
>
> what about
>
>   #+begin_src shell :results list
>     bash -c env | grep GIM
>   #+end_src
>
>   #+RESULTS:
>
> That's pretty surprising. I would have expected running it directly to actually run my profile.
>
> Shockingly
>
>   #+begin_src shell :results list
>     bash --rcfile ~/.bashrc -c env | grep GIM
>   #+end_src
>
>   #+RESULTS:
>
> That is *still* nothing!
>
> Sanity is restored slightly when I run
>
>   #+begin_src shell :results list
>     bash --login -c env | grep GIM
>   #+end_src
>
> which *does* indeed visit ~.bash_profile~ but only slightly.
>
> What is going on, and is there a straightforward way in which I can get shell block to read from a profile?


--
Tim Cross


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-14 21:51 ` Tim Cross
@ 2021-03-15  2:35   ` George Mauer
  2021-03-15  3:02     ` Tim Cross
  0 siblings, 1 reply; 12+ messages in thread
From: George Mauer @ 2021-03-15  2:35 UTC (permalink / raw)
  Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 7284 bytes --]

Hey Tim, thanks for helping out. I commented inline to your response below
but I'll sum up and ask the outstanding questions more directly here as
well.

I think you might have misread what I was doing - I had 3 different
variables set in 3 different places precisely because I want to dissect
things and figure out which profile/rc scripts were run.

Yes, this is emacs running in GUI mode so yes, it doesn't have a shell as a
parent. But that only explains why these environment variables aren't in
emacs itself, not the spawned bash or zsh processes

So to sum up the specific questions. My ~shell-file-name~ is ~/bin/zsh~
which seems to be what ~ob-shell~ is passing down to be run. So why on
earth does my ~GIM_ZSHRC~ variable not show up here?

  #+begin_src shell
    env
  #+end_src

When I actually directly call bash

 #+begin_src shell
    bash -c env
  #+end_src

Why would the output not include ~GIM_BASHRC~ - it should have been run,
right?

What about when I call this? Even with explicitly selecting the rc file to
run, it seems to not

  #+begin_src shell
    bash --rcfile ~/.bashrc -c env
  #+end_src

Finally, the outstanding question about ~ob-shell~ is if there is any way
to force it to run the shell processes' rc-script? I really would have
expected it to be run in the above situations already...

-----------

>
> Is this perhaps on a Mac where Emacs is started from the dock?


Yup like I said, its in GUI mode so I understand why those environment
variables aren't within emads itself


> If so, it
> could be because on the mac, applications started from the dock are not
> executed inside a login shell. Do you get different results if you start
> emacs from within a terminal?


Yup I do, but thats why I move on to the test where I run `bash` directly


> I am also a little confused by your examples. Some of them are
> attempting to source .bash_profile, others .bashrc and others .zshrc.
>

I created the three environment variables I indicated and placed one in
each file so that I could test which profile file ran


> Which shell are you using and which files do you have? I get the feeling
> that in your frustration, you have taken a 'shotgun' approach and added
> the variable everywhere.


That's exactly what I'm trying to avoid here. I *did* add variables
everywhere, but I added *different* variables everywhere so that I can see
exactly which profile ran.


> For some reason, there seems to be some confusion these days about the
> difference between .profile, .bash_profile, .bashrc, .zsh_profile and
> .zshrc. In particular, I frequently see incorrect/wrong advice regarding
> the use of 'profile' and 'rc' files. Most of it can
> be blamed on wrong advice in forums like stack overflow!
>

It is certainly confusing but I think I got a handle on it mostly. If
it's a login shell you'll run a profile, if it's not you'll run the default
rc file unless one of the options were specified. I think each is named
specific to each shell name but oftentimes you chain them together in
practice.


> I would also experiment with just dumping out the output of 'env' and
> not run it through grep so that you can see what is being defined.


I did, that just isn't conducive to posting on an email list ;)

iI also think it is a good dea to be explicit about the shell so that you
> have more
> control/understanding over what is being run e.g. put the line
>

Yeah, I suppose I could do a prologue with a hashbang, but I debugged into
the source and it's just ~shell-file-name~ which in my case is ~/bin/zsh~

In very broad terms (glossing over some of the subtleties, which is
> likely the cause of some of your issues), the 'profile' files are only
> sourced for login shells and the 'rc' files are sourced whenever a new
> shell process is run. Note that these processes run in a hierarchy i.e.
> shell processes have a parent process. Some things have to be set in
> your 'profile' (or are better set there) while other things must be set
> in your 'rc' file. For example, setting PATH in your 'profile' is normal
> because you typically just want that set once and then 'exported' to all
> child processes. Setting a dynamic prompt which changes depending on the
> directory your in (or because it has some other dynamic data, like the
> time) need to be set in your 'rc' file because these are sourced before
> each shell process is executed. I the 'old days' it was important to get
> these distinctions correct because sourcing the files could have a
> performance impact - not as big an issue these days.
>

Great history, thanks, that's mostly what I was thinking but gives me
useful background

These days, things seem to have become even more confusing in an attempt
> to make things easier. I often see people with a .profile, a
> .bash_profile, a .bashrc, a .zsh_profile and a .zshrc with variables set
> and exported mixed in across all these files.


Don't forget that many tools from homebrew to pyenv install scripts to
ansible will start modifying these for you


> This is a source of
> terrible confusion and unexpected results. Some 'canned' shell
> configurations, like 'oh-my-zsh' also try to be extra helpful by
> sourcing files which are not normally sourced by that shell (to make
> smoother migration from bash shells for example). Sometimes, it can be
> helpful to put a line like the following into each of these files
>
> echo "Executing <filename> at `date`" >> ~/profile.log
>
> just to see what is getting executed when (you won't want to leave this
> there - just for diagnostic and experimentation to help understand when
> things are being sourced. You could even dump out the output of 'env' so
> that you can see how the environment is being changed as each of these
> files executes.
>
>
Yup, thanks.


> George Mauer <gmauer@gmail.com> writes:
>
> > I am confused why no matter how I try to run shell commands they seem to
> be missing variables exported in profiles.
> >
> > I have added 3 variables to various startup scripts
> >
> >   - ~./bash-profile~ :: ~export GIM_BASH_PROFILE="yes"~
> >   - ~./bashrc~ :: ~export GIM_BASHRC="yes"~
> >   - ~./zshrc~ :: ~export GIM_ZSHRC="yes"~
> >
> > I am running emacs in GUI mode so I get why none of these are available
> *directly* in emacs, so then I try
> >
> >   #+begin_src shell :results list
> >     env | grep GIM
> >   #+end_src
> >
> >   #+RESULTS:
> >
> > Ok that's kinda surprising, but I suppose it could be running ~/bin/zsh~
> (that's my ~shell-file-name~) directly
> >
> > what about
> >
> >   #+begin_src shell :results list
> >     bash -c env | grep GIM
> >   #+end_src
> >
> >   #+RESULTS:
> >
> > That's pretty surprising. I would have expected running it directly to
> actually run my profile.
> >
> > Shockingly
> >
> >   #+begin_src shell :results list
> >     bash --rcfile ~/.bashrc -c env | grep GIM
> >   #+end_src
> >
> >   #+RESULTS:
> >
> > That is *still* nothing!
> >
> > Sanity is restored slightly when I run
> >
> >   #+begin_src shell :results list
> >     bash --login -c env | grep GIM
> >   #+end_src
> >
> > which *does* indeed visit ~.bash_profile~ but only slightly.
> >
> > What is going on, and is there a straightforward way in which I can get
> shell block to read from a profile?
>
>
> --
> Tim Cross
>
>

[-- Attachment #2: Type: text/html, Size: 10025 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-15  2:35   ` George Mauer
@ 2021-03-15  3:02     ` Tim Cross
  2021-03-15 17:49       ` George Mauer
  0 siblings, 1 reply; 12+ messages in thread
From: Tim Cross @ 2021-03-15  3:02 UTC (permalink / raw)
  To: emacs-orgmode


comments in-line ...

George Mauer <gmauer@gmail.com> writes:

> Hey Tim, thanks for helping out. I commented inline to your response below but I'll sum up and ask the outstanding questions more directly here as well.
>
> I think you might have misread what I was doing - I had 3 different variables set in 3 different places precisely because I want to dissect things and figure
> out which profile/rc scripts were run.
>
> Yes, this is emacs running in GUI mode so yes, it doesn't have a shell as a parent. But that only explains why these environment variables aren't in
> emacs itself, not the spawned bash or zsh processes
>

To clarify, the GUI mode is unrelated. You can run in GUI mode from a
terminal and the emacs process will inherit the environment in the
terminal. If that terminal is a login terminal (i.e. terminal shell was
run as a login shell), the 'profile' file will be sourced and the 'rc'
file will have been sourced. If not a login shell, only the rc file will
have been sourced.

If on the other hand, Emacs is started from the dock, it is started in a
completely different process chain and is not a child of a login
process. This is why, if you want your emacs to have /usr/local/bin in
the path, you have to add it to /etc/paths or /etc/path.d whereas if you
start emacs from within a terminal (GUI or text mode), you only need to
add /usr/local/bin to your PATH setting in .profile (just an example to
highlight the difference between running from in a terminal and running
from the dock).

> So to sum up the specific questions. My ~shell-file-name~ is ~/bin/zsh~ which seems to be what ~ob-shell~ is passing down to be run. So why on earth
> does my ~GIM_ZSHRC~ variable not show up here?
>
>   #+begin_src shell
>     env
>   #+end_src
>
> When I actually directly call bash
>
>  #+begin_src shell
>     bash -c env
>   #+end_src
>

Have a closer look on the section in the bash manual on the difference
between interactive and non-interactive shells. (also holds for zsh).
Basically, the 'rc' files are not sourced for non-interactive shells.

> Why would the output not include ~GIM_BASHRC~ - it should have been run, right?
>

No. Adding the -c means it is a non-interactive shell, so no .bashrc
sourcing.


> What about when I call this? Even with explicitly selecting the rc file to run, it seems to not
>
>   #+begin_src shell
>     bash --rcfile ~/.bashrc -c env
>   #+end_src
>

Same issue here. --rcfile only has effect in interactive shells.

> Finally, the outstanding question about ~ob-shell~ is if there is any way to force it to run the shell processes' rc-script? I really would have expected it to
> be run in the above situations already...
>

You could try sourcing it e.g.

#+begin_src shell
source ~/.bashrc
env
#+end_src

or use 'shorthand' dot

#+begin_src shell
. ~/.bashrc
env
#+end_src

there are also some options you can add at the 'shebang' line i.e.

#!/bin/bash -l

or

#!/bin/bash -i

which will change the behaviour.

There is a lot of 'meat' in the bash man page and there is a lot of
additional information in the bash info pages. However, both can be a
bit terse and because the info is very 'dense', it is very easy to miss
key points.

In order to have environment variables available inside your org source
blocks, you really need to

- have them in the environment inherited by emacs when it starts. This
  will depend how you start Emacs (i.e from within an interactive shell
  vs from the dock). Note that you typically don't see this issue under
  Linux because in most Linux setups, the X environment is started
  inside a login shell. So everything started as part of the X session,
  like a dock, is a child of the login process and therefore inherits
  the login environment. On a mac, the dock is not part of the login
  shell, so it only inherits what is in the system wide bash profile
  file.

- Ensure your source block run as interactive and/or login shells using
  shebang options like -i or -l

- explicitly source the .profile or .bashrc file using a source call

- pass the environment variable in on the command line e.g.

#+begin_src shell
FRED=barney env
#+end_src

will result in

FRED=barney

being in the output from 'env'.


> -----------
>
>  Is this perhaps on a Mac where Emacs is started from the dock?
>
> Yup like I said, its in GUI mode so I understand why those environment variables aren't within emads itself
>

It is actually a little more subtle. It isn't because your running in
GUI mode those variables are not there. It is because your running from
the dock. Run it in GUI mode from within a login terminal and all those
variables will be 'in' emacs.

<snip>

> It is certainly confusing but I think I got a handle on it mostly. If it's a login shell you'll run a profile, if it's not you'll run the default rc file unless one of the
> options were specified. I think each is named specific to each shell name but oftentimes you chain them together in practice.
>

There is also a difference between interactive and non-interactive
shells. I suspect this is the root cause of your issue. The source block
being run are non-interactive.

--
Tim Cross


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-15  3:02     ` Tim Cross
@ 2021-03-15 17:49       ` George Mauer
  2021-03-15 19:53         ` Tim Cross
  2021-03-16 12:20         ` Maxim Nikulin
  0 siblings, 2 replies; 12+ messages in thread
From: George Mauer @ 2021-03-15 17:49 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 6041 bytes --]

Thanks a lot! The interactive/non-interactive was indeed the core issue.
Extra frustrating because it seems like supplying `--rcfile` does nothing
if you *do* use `-c` but *don't* use `-i`...ah ad-hoc cli design.

As a general solution, I've found that adding this block in my org buffer
will make shell (which is zsh in my case) run in interactive mode for all
of these

* Local Variables :noexport:
  :PROPERTIES:
  :VISIBILITY: folded
  :END:
  local variables:
  shell-file-name: "/bin/zsh -i"
  end:

On Sun, Mar 14, 2021 at 11:04 PM Tim Cross <theophilusx@gmail.com> wrote:

>
> comments in-line ...
>
> George Mauer <gmauer@gmail.com> writes:
>
> > Hey Tim, thanks for helping out. I commented inline to your response
> below but I'll sum up and ask the outstanding questions more directly here
> as well.
> >
> > I think you might have misread what I was doing - I had 3 different
> variables set in 3 different places precisely because I want to dissect
> things and figure
> > out which profile/rc scripts were run.
> >
> > Yes, this is emacs running in GUI mode so yes, it doesn't have a shell
> as a parent. But that only explains why these environment variables aren't
> in
> > emacs itself, not the spawned bash or zsh processes
> >
>
> To clarify, the GUI mode is unrelated. You can run in GUI mode from a
> terminal and the emacs process will inherit the environment in the
> terminal. If that terminal is a login terminal (i.e. terminal shell was
> run as a login shell), the 'profile' file will be sourced and the 'rc'
> file will have been sourced. If not a login shell, only the rc file will
> have been sourced.
>
> If on the other hand, Emacs is started from the dock, it is started in a
> completely different process chain and is not a child of a login
> process. This is why, if you want your emacs to have /usr/local/bin in
> the path, you have to add it to /etc/paths or /etc/path.d whereas if you
> start emacs from within a terminal (GUI or text mode), you only need to
> add /usr/local/bin to your PATH setting in .profile (just an example to
> highlight the difference between running from in a terminal and running
> from the dock).
>
> > So to sum up the specific questions. My ~shell-file-name~ is ~/bin/zsh~
> which seems to be what ~ob-shell~ is passing down to be run. So why on earth
> > does my ~GIM_ZSHRC~ variable not show up here?
> >
> >   #+begin_src shell
> >     env
> >   #+end_src
> >
> > When I actually directly call bash
> >
> >  #+begin_src shell
> >     bash -c env
> >   #+end_src
> >
>
> Have a closer look on the section in the bash manual on the difference
> between interactive and non-interactive shells. (also holds for zsh).
> Basically, the 'rc' files are not sourced for non-interactive shells.
>
> > Why would the output not include ~GIM_BASHRC~ - it should have been run,
> right?
> >
>
> No. Adding the -c means it is a non-interactive shell, so no .bashrc
> sourcing.
>
>
> > What about when I call this? Even with explicitly selecting the rc file
> to run, it seems to not
> >
> >   #+begin_src shell
> >     bash --rcfile ~/.bashrc -c env
> >   #+end_src
> >
>
> Same issue here. --rcfile only has effect in interactive shells.
>
> > Finally, the outstanding question about ~ob-shell~ is if there is any
> way to force it to run the shell processes' rc-script? I really would have
> expected it to
> > be run in the above situations already...
> >
>
> You could try sourcing it e.g.
>
> #+begin_src shell
> source ~/.bashrc
> env
> #+end_src
>
> or use 'shorthand' dot
>
> #+begin_src shell
> . ~/.bashrc
> env
> #+end_src
>
> there are also some options you can add at the 'shebang' line i.e.
>
> #!/bin/bash -l
>
> or
>
> #!/bin/bash -i
>
> which will change the behaviour.
>
> There is a lot of 'meat' in the bash man page and there is a lot of
> additional information in the bash info pages. However, both can be a
> bit terse and because the info is very 'dense', it is very easy to miss
> key points.
>
> In order to have environment variables available inside your org source
> blocks, you really need to
>
> - have them in the environment inherited by emacs when it starts. This
>   will depend how you start Emacs (i.e from within an interactive shell
>   vs from the dock). Note that you typically don't see this issue under
>   Linux because in most Linux setups, the X environment is started
>   inside a login shell. So everything started as part of the X session,
>   like a dock, is a child of the login process and therefore inherits
>   the login environment. On a mac, the dock is not part of the login
>   shell, so it only inherits what is in the system wide bash profile
>   file.
>
> - Ensure your source block run as interactive and/or login shells using
>   shebang options like -i or -l
>
> - explicitly source the .profile or .bashrc file using a source call
>
> - pass the environment variable in on the command line e.g.
>
> #+begin_src shell
> FRED=barney env
> #+end_src
>
> will result in
>
> FRED=barney
>
> being in the output from 'env'.
>
>
> > -----------
> >
> >  Is this perhaps on a Mac where Emacs is started from the dock?
> >
> > Yup like I said, its in GUI mode so I understand why those environment
> variables aren't within emads itself
> >
>
> It is actually a little more subtle. It isn't because your running in
> GUI mode those variables are not there. It is because your running from
> the dock. Run it in GUI mode from within a login terminal and all those
> variables will be 'in' emacs.
>
> <snip>
>
> > It is certainly confusing but I think I got a handle on it mostly. If
> it's a login shell you'll run a profile, if it's not you'll run the default
> rc file unless one of the
> > options were specified. I think each is named specific to each shell
> name but oftentimes you chain them together in practice.
> >
>
> There is also a difference between interactive and non-interactive
> shells. I suspect this is the root cause of your issue. The source block
> being run are non-interactive.
>
> --
> Tim Cross
>
>

[-- Attachment #2: Type: text/html, Size: 7218 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-15 17:49       ` George Mauer
@ 2021-03-15 19:53         ` Tim Cross
  2021-03-16  0:52           ` Steven Harris
  2021-03-16 12:20         ` Maxim Nikulin
  1 sibling, 1 reply; 12+ messages in thread
From: Tim Cross @ 2021-03-15 19:53 UTC (permalink / raw)
  To: emacs-orgmode


George Mauer <gmauer@gmail.com> writes:

> Thanks a lot! The interactive/non-interactive was indeed the core issue. Extra frustrating because it seems like supplying `--rcfile` does nothing if you
> *do* use `-c` but *don't* use `-i`...ah ad-hoc cli design.
>

It certainly can seem rather ad hoc. However, it actually makes sense on
some levels. If you use -c your telling the shell to execute a command
and then exit. By definition, this is non-interactive. This is covered
in the manual.

Where it becomes confusing is when your mixing in different options as
some override others. So, provided you include -i with -c, it will be
forced into interactive i.e. -i overrides the non-interactive status
added with -c. If you add -s, telling the shell to read input from
stdin, you also override non-interactive status.

The other possible solution to your situation is to ensure
Emacs runs inside an environment which has all your exported variables
i.e. inside your login shell environment. There are a few ways to do
this, but probably the easiest is to create a script which opens a login
shell, then calls Emacs (may need to use open - not sure) and Emacs will
inherit your environment. Advantage is that processes you then spawn
from within Emacs will also inherit that environment. You then add this
script as the executable in the dock rather than calling Emacs directly.

One thing to watch out for is that if your also using oh-my-zsh, it
setups up some aliases with the name emacs which actually call
emacsclient. This can be confusing as it means running just 'emacs' in
the shell will run the alias and not actually run Emacs directly. Things
can be even more confusing as there are also multiple ways to install
Emacs on the mac and they are all slightly different with respect to how
they setup things.

What I find hardest with writing shell stuff is that I simply don't seem
to do it much anymore. My brain cache is just too small and when I find
it necessary to write a shell script again, all that knowledge has been
flushed! Once upon a time, many moons ago, I could write shell scripts
that used sed, awk, cut, uniq etc without even needing to look at the
man pages. These days, I have to check the bash man page just to
remember what the expr operators are!

--
Tim Cross


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-15 19:53         ` Tim Cross
@ 2021-03-16  0:52           ` Steven Harris
  0 siblings, 0 replies; 12+ messages in thread
From: Steven Harris @ 2021-03-16  0:52 UTC (permalink / raw)
  To: Tim Cross; +Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 2702 bytes --]

Well on my mac Emacs is launched by Ruby.  I remember having to allow ruby
to do that two years ago when I set this up.

But thanks for sharing your expertise.  I've been a unixy admin for 20
years and didn't know a lot of that.

Cheers

Steven.

On Tue, 16 Mar 2021 at 07:34, Tim Cross <theophilusx@gmail.com> wrote:

>
> George Mauer <gmauer@gmail.com> writes:
>
> > Thanks a lot! The interactive/non-interactive was indeed the core issue.
> Extra frustrating because it seems like supplying `--rcfile` does nothing
> if you
> > *do* use `-c` but *don't* use `-i`...ah ad-hoc cli design.
> >
>
> It certainly can seem rather ad hoc. However, it actually makes sense on
> some levels. If you use -c your telling the shell to execute a command
> and then exit. By definition, this is non-interactive. This is covered
> in the manual.
>
> Where it becomes confusing is when your mixing in different options as
> some override others. So, provided you include -i with -c, it will be
> forced into interactive i.e. -i overrides the non-interactive status
> added with -c. If you add -s, telling the shell to read input from
> stdin, you also override non-interactive status.
>
> The other possible solution to your situation is to ensure
> Emacs runs inside an environment which has all your exported variables
> i.e. inside your login shell environment. There are a few ways to do
> this, but probably the easiest is to create a script which opens a login
> shell, then calls Emacs (may need to use open - not sure) and Emacs will
> inherit your environment. Advantage is that processes you then spawn
> from within Emacs will also inherit that environment. You then add this
> script as the executable in the dock rather than calling Emacs directly.
>
> One thing to watch out for is that if your also using oh-my-zsh, it
> setups up some aliases with the name emacs which actually call
> emacsclient. This can be confusing as it means running just 'emacs' in
> the shell will run the alias and not actually run Emacs directly. Things
> can be even more confusing as there are also multiple ways to install
> Emacs on the mac and they are all slightly different with respect to how
> they setup things.
>
> What I find hardest with writing shell stuff is that I simply don't seem
> to do it much anymore. My brain cache is just too small and when I find
> it necessary to write a shell script again, all that knowledge has been
> flushed! Once upon a time, many moons ago, I could write shell scripts
> that used sed, awk, cut, uniq etc without even needing to look at the
> man pages. These days, I have to check the bash man page just to
> remember what the expr operators are!
>
> --
> Tim Cross
>
>

[-- Attachment #2: Type: text/html, Size: 3306 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-15 17:49       ` George Mauer
  2021-03-15 19:53         ` Tim Cross
@ 2021-03-16 12:20         ` Maxim Nikulin
  2021-03-16 13:21           ` George Mauer
  1 sibling, 1 reply; 12+ messages in thread
From: Maxim Nikulin @ 2021-03-16 12:20 UTC (permalink / raw)
  To: emacs-orgmode

On 16/03/2021 00:49, George Mauer wrote:
>    shell-file-name: "/bin/zsh -i"

I am afraid, you should be prepared to face some problem accidentally. 
The value of this variable is used to execute the specified file
("zsh -i" in the "/bin" directory, I do not think, you have such file), 
not as a part of shell command. shell-file-name in namely file name to 
be executed with shell-command-switch as first argument (separate 
arguments, not merged into a string) to run shell commands (next argument).

Environment variables could be set on OS level, inside emacs 
https://www.gnu.org/software/emacs/manual/html_node/emacs/Environment.html 
, etc. It is hard to suggest something since you have not described the 
problem you are trying to solve. Tim in details explained why you 
attempt to solve it did not work, but the problem (or the goal) is still 
unknown.



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-16 12:20         ` Maxim Nikulin
@ 2021-03-16 13:21           ` George Mauer
  2021-03-16 16:49             ` Nick Dokos
                               ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: George Mauer @ 2021-03-16 13:21 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1907 bytes --]

I understand why you say that maxim but testing that this worked was the
first thing I did and it does work. I was surprised as well. I haven't
debugged all the way into the eval functions to see why this works but my
guess is that the authors were pretty smart about figuring out which
executable to invoke.

As for the problem I'm trying to solve, there isn't one exactly. This is
more me hacking on something I don't fully understand because it regularly
trips me up.

I do still wonder what would be the disadvantage of just configuring it to
do --login by default and doing all configuration in profile scripts. It
would be unconventional yes, but it would also make dynamic scoping of
environment variable effectively opt-in via --noprofile rather than opt-out
(which imo is how it should be). I would assume that uses extra resources
or risks improperly handling crashed processes, but I can't find anything
to that effect in the docs

On Tue, Mar 16, 2021, 07:32 Maxim Nikulin <manikulin@gmail.com> wrote:

> On 16/03/2021 00:49, George Mauer wrote:
> >    shell-file-name: "/bin/zsh -i"
>
> I am afraid, you should be prepared to face some problem accidentally.
> The value of this variable is used to execute the specified file
> ("zsh -i" in the "/bin" directory, I do not think, you have such file),
> not as a part of shell command. shell-file-name in namely file name to
> be executed with shell-command-switch as first argument (separate
> arguments, not merged into a string) to run shell commands (next argument).
>
> Environment variables could be set on OS level, inside emacs
> https://www.gnu.org/software/emacs/manual/html_node/emacs/Environment.html
> , etc. It is hard to suggest something since you have not described the
> problem you are trying to solve. Tim in details explained why you
> attempt to solve it did not work, but the problem (or the goal) is still
> unknown.
>
>
>

[-- Attachment #2: Type: text/html, Size: 2513 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-16 13:21           ` George Mauer
@ 2021-03-16 16:49             ` Nick Dokos
  2021-03-16 20:32             ` Tim Cross
  2021-03-18 14:59             ` Maxim Nikulin
  2 siblings, 0 replies; 12+ messages in thread
From: Nick Dokos @ 2021-03-16 16:49 UTC (permalink / raw)
  To: emacs-orgmode

George Mauer <gmauer@gmail.com> writes:

> I understand why you say that maxim but testing that this worked was the first thing I did
> and it does work. I was surprised as well. I haven't debugged all the way into the eval
> functions to see why this works but my guess is that the authors were pretty smart about
> figuring out which executable to invoke.
>

Starting with `emacs -q' I evaluate

    (setq shell-file-name "bash -i")

in the *scratch* buffer and then do `M-x shell'. I get

    apply: Searching for program: No such file or directory, bash -i


If I do

    (setq shell-file-name "/bin/bash -i")

I get

    emacs: /bin/bash -i: No such file or directory

    Process shell exited abnormally with code 127

The trouble is that `shell-file-name' may be used much more widely than you expect.

> As for the problem I'm trying to solve, there isn't one exactly. This is more me hacking on
> something I don't fully understand because it regularly trips me up.
>
> I do still wonder what would be the disadvantage of just configuring it to do --login by
> default and doing all configuration in profile scripts. It would be unconventional yes, but
> it would also make dynamic scoping of environment variable effectively opt-in via
> --noprofile rather than opt-out (which imo is how it should be). I would assume that uses
> extra resources or risks improperly handling crashed processes, but I can't find anything to
> that effect in the docs
>
> On Tue, Mar 16, 2021, 07:32 Maxim Nikulin <manikulin@gmail.com> wrote:
>
>     On 16/03/2021 00:49, George Mauer wrote:
>     >    shell-file-name: "/bin/zsh -i"
>    
>     I am afraid, you should be prepared to face some problem accidentally.
>     The value of this variable is used to execute the specified file
>     ("zsh -i" in the "/bin" directory, I do not think, you have such file),
>     not as a part of shell command. shell-file-name in namely file name to
>     be executed with shell-command-switch as first argument (separate
>     arguments, not merged into a string) to run shell commands (next argument).
>    
>     Environment variables could be set on OS level, inside emacs
>     https://www.gnu.org/software/emacs/manual/html_node/emacs/Environment.html
>     , etc. It is hard to suggest something since you have not described the
>     problem you are trying to solve. Tim in details explained why you
>     attempt to solve it did not work, but the problem (or the goal) is still
>     unknown.
>

-- 
Nick

"There are only two hard problems in computer science: cache
invalidation, naming things, and off-by-one errors." -Martin Fowler



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-16 13:21           ` George Mauer
  2021-03-16 16:49             ` Nick Dokos
@ 2021-03-16 20:32             ` Tim Cross
  2021-03-18 14:59             ` Maxim Nikulin
  2 siblings, 0 replies; 12+ messages in thread
From: Tim Cross @ 2021-03-16 20:32 UTC (permalink / raw)
  To: emacs-orgmode


George Mauer <gmauer@gmail.com> writes:

> I do still wonder what would be the disadvantage of just configuring it to do --login by default and doing all configuration in profile scripts. It would be
> unconventional yes, but it would also make dynamic scoping of environment variable effectively opt-in via --noprofile rather than opt-out (which imo is
> how it should be). I would assume that uses extra resources or risks improperly handling crashed processes, but I can't find anything to that effect in the
> docs

The following is long, but may provide some of the context you are
looking for to help understand all the moving parts involved here. Some
of ti is not 100% accurate, but trying to be 100% accurate would make it
longer and would not necessarily help with the mental model needed to
understand how this all fits together. Hopefully, this has a reasonable
balance between accuracy and simplicity!

While there is certainly aspects of shell architecture which are less
relevant in a modern computing environment, the way it all works is
actually pretty good. It can sometimes help to remember what early Unix
environments were like and what the resource constraints were to
understand some of the design decisions. A time when memory and disk
storage was extremely expensive and in short supply, where CPUs were
slower and less capable than those commonly found in a modern washing
machine. This was a time where every CPU cycle, every memory bit and
every byte of storage had to be justified and used efficiently.

The 'login' shell actually has a special purpose and a few subtleties
associated with it that may not be obvious at first. For example, the
login shell usually records a user's login in a few system files like
wtmp and utmp. The idea is that the login shell will be the 'root' of a
user's process tree. One of its key roles is to setup the environment
which will be inherited by all the other (child) processes which the
user initiates. This includes some things which you only want run once
and processes which must run as parents to all other processes. A good
example is setting up an ssh agent and adding ssh keys to that agent.
You only want this to occur once, so you might add this to your .profile
(or whatever the shell equivalent is, such as .bash_profile or
.zsh_profile). More critical is the requirement that the ssh agent must
be run inside a parent process for child processes to be able to use it.
This means it needs to be near the 'root' login process to ensure all
children are able to take advantage of the service it provides.
(Keep in mind that some platforms, like the mac, have created a whole
new architecture for managing keys etc and even on Linux, it is rarely
necessary to run ssh-agent like we did in the 'old days' as that
functionality has been subsumed into desktop environments like gnome)

It is also here that you will define static environment variables i.e.
those which will not change during the lifetime of the session and which
are exported, meaning they are made available in the environments of
child processes. Examples are setting up things like PATH, EMAIL etc.
Some common environment variables, like USER, HOME etc are done
automatically as part of the system wide profile in /etc/profile or the
system wide path defined in /etc/paths and /etc/paths.d etc.

In addition to these static environment variables are more dynamic ones
which change and therefore need to be updated with each new shell
process. This can include variables like PWD and CWD which track the
parent and current working directory or the PS1 and PS2 variables which
contain details about your shell prompt that may include dynamic
information such as the current working directory, current date/time or
status of the git repository associated with the current working
directory. This is essentially the role fulfilled by the 'rc' files,
like .bashrc. As these dynamic enironment variables tend to only be
relevant for interactive shells, the rc file is only 'sourced' for those
shells.

When you execute a command, it creates a new process which has an
execution environment associated with it (there are some exceptions,
such as built-in shell commands that run inside the current process and
command 'modifiers' like 'exec' which replace the current process with
the command being executed). Some of these processes will be very short
lived, executing a single command or possibly run for hours, days, weeks
(such as Emacs). This process is a child process of the process which
ran/executed the command. You can use the -f (forest) switch to ps to
see the relationship between processes. Those processes in turn may
execute more child processes (such as when Emacs creates a shell process
to perform some task, like run a compilation task, spawn a shell or
terminal, etc. The environment each of these processes inherits consists
of the exported variables defined in the parent process. This is
typically all the exported variables from the login process (as it is
the parent of all) and any variables exported by parent processes in the
process hierarchy (such as any exported as part of an interactive shell
which sourced .bashrc for example) or is defined and exported in a
parent (such as part of a shell script which then executes the command
which creates the child process.

So, in general, you don't want to run all or many of your processes as a
login shell. At the very least it is wasting resources and at the worst
it could actually cause confusion or break things because it is causing
things to be run multiple times which should only be run once.

I suspect some of the confusion here is being cause because of the
different model approach used by the Mac OS. On the mac, you actually
have at least two process trees (I'm not a mac expert, so it is possible
there are more than two - in fact I'm pretty sure there are, but for
explanation purposes....). On the mac you have your login process tree
and your 'dock' (launcher) process tree. The dock process tree is not
rooted as the child of a login shell, so there is no sourcing of
.profile and it is not an interactive shell, so no .bashrc either. The
execution environment associated with processes it spawns (such as when
you run a command) only consist of the global system environment setup
by the system prfile in /etc/profile, /etc/paths and /etc/paths.d and
any environment variables created and exported by the process itself
(i.e. using the setenv command in your emacs init.el). Whether emacs is
run in terminal mode or in GUI mode has nothing to do with what
environment context it has. The context is determined by the environment
context of the process parent.

So a common way to ensure your .profile environment variables are
available in Emacs when it is run from the dock is to use a shell
wrapper script which first sources .profile to create and export the
variables in .pofile and then run emacs. Often you won't just make it a
login shell, but simply source .profile. It is this script which is
added to the dock and is executed to start Emacs, ensuring it has your
.profile variables set and exported to the child process, Emacs. In
turn, any child processes created by Emacs will also include this
environment context (such as wehn you open an emacs terminal, run M-x
shell or execute org source blocks). 

The other approach is to just add the variables you need using 'setenv'
i your emacs init.el file. Often, there are only a few additional
variables you want inside of Emacs and child processes it creates, so
adding them to your init.el file is not hard. The one which is most
often needed is updates to the PATH variable to add additional
directories to search for executable files. You can use setenv to do
this or you can use the exec-path package or you can do what I do, which
is add these additional paths to /etc/paths.d. I don't bother with the
wrapper script on the Mac. There are only a couple of additional
variables I need defined, so I set them in my init.el using setenv. 

-- 
Tim Cross


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: How to get shell source blocks to read my profile?
  2021-03-16 13:21           ` George Mauer
  2021-03-16 16:49             ` Nick Dokos
  2021-03-16 20:32             ` Tim Cross
@ 2021-03-18 14:59             ` Maxim Nikulin
  2 siblings, 0 replies; 12+ messages in thread
From: Maxim Nikulin @ 2021-03-18 14:59 UTC (permalink / raw)
  To: emacs-orgmode

On 16/03/2021 20:21, George Mauer wrote:
> 
> I do still wonder what would be the disadvantage of just configuring it 
> to do --login by default and doing all configuration in profile scripts.

At the first glance it at least should not cause great trouble. Most 
shell stuff is written in fool-proof way to avoid loading interactive 
features in non-interactive shell or reinitialize login settings in 
nested shells. Local scripts could be written with less care.

I do not think you need completion functions or changing window title 
during execution of code snippets from emacs.

Self-contained org files have some value, you are trying to put some 
important settings outside. It might be reasonable for personal 
preferences as account names but hardly should be general practice.

On the other hand, I think, it is an equally valid question:
What is the profit?

For some reason your are avoiding over means to set environment 
variables. If you wish just exported environment variables, you could 
always create your own wrapper (untested)

#!/bin/bash

source ~/.config/wundershrc
exec "$0" "$@"

On 17/03/2021 03:32, Tim Cross wrote:
> It can sometimes help to remember what early Unix
> environments were like and what the resource constraints were to
> understand some of the design decisions. A time when memory and disk
> storage was extremely expensive and in short supply, where CPUs were
> slower and less capable than those commonly found in a modern washing
> machine.

Quite recent story is rewriting init scripts to be able to run them with 
dash instead of bash as /bin/sh. On the other hand unavailable features 
require more extensive usage of subprocesses like sed, awk, etc.



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2021-03-18 15:02 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-14 21:30 How to get shell source blocks to read my profile? George Mauer
2021-03-14 21:51 ` Tim Cross
2021-03-15  2:35   ` George Mauer
2021-03-15  3:02     ` Tim Cross
2021-03-15 17:49       ` George Mauer
2021-03-15 19:53         ` Tim Cross
2021-03-16  0:52           ` Steven Harris
2021-03-16 12:20         ` Maxim Nikulin
2021-03-16 13:21           ` George Mauer
2021-03-16 16:49             ` Nick Dokos
2021-03-16 20:32             ` Tim Cross
2021-03-18 14:59             ` Maxim Nikulin

Code repositories for project(s) associated with this inbox:

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).