emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Matt <matt@excalamus.com>
To: "Ihor Radchenko" <yantar92@posteo.net>
Cc: "emacs-orgmode@gnu.org" <emacs-orgmode@gnu.org>
Subject: Re: bash source code block: problem after ssh commands
Date: Fri, 17 Nov 2023 23:07:57 +0100	[thread overview]
Message-ID: <18bdf538f2f.126bad4763316098.8581777358227217138@excalamus.com> (raw)
In-Reply-To: <871qcod9ad.fsf@localhost>


 ---- On Fri, 17 Nov 2023 10:20:28 +0100  Ihor Radchenko  wrote --- 

 > This has nothing to do with Emacs comint and this is also not a bug in
 > Emacs 

Ihor, there were two claims made in the original report.  I was referring to Claim 2.  That deals with M-x shell and therefore comint-mode.

Regarding Claim 1:

- Can anyone verify Claim 1?
- Is anyone else unable to verify Claim 1 (like me)?
- What versions are people using?
  + M-x org-version
  + M-x emacs-version

I'm running Org mode version 9.7-pre (release_9.6.10-903-g9183e3.dirty @ /home/ahab/.emacs.d/straight/build/org/) on GNU Emacs 29.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.37, cairo version 1.16.0).

* The original report has two claims:
** Claim 1.
The following block is expected to write a remote file called "foo_file" with contents "foo" as well as give "bar" as the result.

    #+begin_src bash :results output
    ssh cochard@fruc.u-strasbg.fr "echo foo>foo_file"
    echo "bar"
    #+end_src

The reported behavior is that "foo_file" is created with "foo" (with "foo" is not stated, but implied) and "bar" is *not* given as the result.

** Claim 2.
Copying and pasting the two lines from the first claim into a terminal like xfce4-terminal executes the ssh line as expected and outputs the result of the second line.  It was noted that this does not happen with M-x shell.

* Comments about the claims:
** Comment 1.
tl;dr I can't reproduce the claim that "bar" is *not* the result.  The result is "bar" for me.

The exact "expected behavior" for a shell block is a little fuzzy.  According to my analysis (given below), what Alain reports (remote file and no "bar") is the "expected" behavior.  What I see (no remote file and "bar") is actually "unexpected".

I used the following to test the claim:

    #+begin_src bash :results output
    ssh localhost "echo foo>foo_file"
    echo "bar"
    #+end_src

I am unable to reproduce the reported behavior (of "bar" not returning).  Instead, I get an ssh-askpass permission denied error, foo_file is not created, and "bar" is given as the result.  I do not see anywhere in the thread that the original claim was reproduced.

The thread preceded something like follows.

Leo Butler suggested two work arounds:

- add the -f to the ssh command
- add a semi-colon and line continuation to the first line.

Russell Adams suggested another work around:

- add -n to the ssh command

Ihor identified that a non-session call does something like the following command:

    bash -c bash /tmp/temp-file-with-source-block-code.sh

where

    ----- /tmp/temp-file-with-source-block-code -----
    ssh localhost "echo foo>foo_file"
    echo "bar" | tee /tmp/bar.txt
    -------------------------------------------------

The second line (significantly different from the original report) pipes the echo result to stdout and to a file, bar.txt.  Writing to a file allows us to confirm if that line was executed.

Ihor suggested that

    bash -c bash /tmp/temp-file-with-source-block-code.sh

does not run the second line because an interactive password prompt is displayed by ssh.  The reasoning is that the prompt hangs the process while waiting for input and the second line never runs.  Indeed, running the command does not produce /tmp/bar.txt.

Ihor is correct about prompts messing with shell blocks (this is not the first time he's seen this).  However, the way it's stated does not demonstrate it. This is because Emacs does *not* make a call like

    bash -c bash /tmp/temp-file-with-source-block-code.sh

Alain responded by pointing out that

    bash -c bash /tmp/temp-file-with-source-block-code.sh

does not execute the first line.  This is true.  Consider calling

    bash -c bash /tmp/two-lines.sh

where

    ------ /tmp/two-lines.sh ------
    echo "first" > /tmp/first.txt
    echo "second" > /tmm/second.txt
    -------------------------------

Neither first.txt or second.txt are created.

Max Nikulin interjected with a helpful reminder that Bash scripting is a snakepit of footguns.  (What Max said is more than that and interesting.  I skip it here because it depends on the form of the call.)

Before trying to untangle what a given Bash command does, we need to be sure what command is actually called.  Unfortunately, there's not a clear Bash command corresponding to how Emacs makes the call.

What happens goes something like this:

1. The Lisp function process-file is called with PROGRAM "bash", INFILE a path to a temp file containing the source block code, and ARGS ("-c" "bash")
2. This information is passed to DEFUN ("call-process"), a Lisp object implemented in C
3. DEFUN ("call-process") forwards this information to the C function call_process
4. call_process calls emacs_spawn
5. emacs_spawn creates a subprocess

A lot of cleaning and setup happens which is dependent on the system (GNU, Window, Darwin, etc.).  There's a call to openp which looks for the executable.  An emacs_pipe is set up (I assume for writing to stdout and stderr).  I'm unable to give a definitive answer as to what precisely emacs_spawn calls.  Do any of the args "get quotes?"  I can't say.

Bruno Barbier commented that his understanding of process-file is that it gets commands from stdin.  Maybe that's what the call to emacs_pipe is doing?

He gives the example:

#+begin_quote
(process-file "bash" "/tmp/test.sh")

is more equivalent to:

cat /tmp/test.sh | bash
#+end_quote

He then proposes an experiment to close stdin.  To do this, he calls

    #+begin_src shell :results output
    exec 0>&-
    echo OK
    #+end_src

He claims that "exec 0<&-" closes stdin.  I believe there is a typo.  It's not clear if it has a negative effect, though.  According to the [[https://tldp.org/LDP/abs/html/io-redirection.html][Advanced Bash-Scripting Guide]],

#+begin_quote
Closing File Descriptors

n<&-

    Close input file descriptor n.
0<&-, <&-

    Close stdin.
n>&-

    Close output file descriptor n.
1>&-, >&-

    Close stdout.
#+end_quote

What Bruno writes corresponds to "closing output file descriptor 0".  I honestly don't know what the difference is between an "output file descriptor" and an "input file descriptor".  I had no luck finding this information in man bash or info bash.

Rerunning the experiment according to the [[https://tldp.org/LDP/abs/html/io-redirection.html][Advanced Bash-Scripting Guide]], the result is the same: "OK" is *not* printed.

    #+begin_src shell :results output
    exec 0<&-
    echo OK
    #+end_src

Doing the following echoes OK for either direction of the redirection:

  -- /tmp/exec-OKlt.sh ---
  exec 0<&-
  echo OK
  ----------------------

  #+begin_example
  bash /tmp/exec-OKlt.sh
  #+end_example

  -- /tmp/exec-OKgt.sh ---
  exec 0>&-
  echo OK
  ----------------------

  #+begin_example
  bash /tmp/exec-OKgt.sh
  #+end_example

The INFILE passed to process-file looks like,

    #+begin_src emacs-lisp
    (process-file
       "bash"
       "/tmp/two-lines.sh"
       '(t "/tmp/babel-mS0Yyg/ob-error-AoxNqH")
       nil
       "-c" "bash")
    #+end_src

So, the call Emacs makes is probably more close to:

    #+begin_example
    cat /tmp/two-lines.sh | bash -c bash
    #+end_example

What this exactly does is unclear to me.  It appears to pass the contents of /tmp/two-lines.sh to a subshell process.  That is, it seems to behave like "bash /tmp/two-lines.sh" is run in a subprocess.

Running this in xfce4-terminal, I get what I expect:

    #+begin_example
    cat /tmp/two-lines.sh | bash -c bash
    #+end_example

Each line is echoed to file so nothing is written to the console.  However, both files are created with the expected text.  Both lines executed.

If I update two-lines to output to std,

    ------ /tmp/two-lines-tee.sh ------
    echo "first"  | tee /tmp/first.txt
    echo "second" | tee /tmp/second.txt
    -----------------------------------

I see "first" and "second" echoed to the console:

    ahab@pequod /tmp$ cat two-lines-tee.sh | bash -c bash
    first
    second

Running the following, neither give an output to the console:

#+begin_example
ahab@pequod /tmp$ cat exec-OKlt.sh | bash -c bash
ahab@pequod /tmp$ cat exec-OKgt.sh | bash -c bash
#+end_example

This is what we see in Org.  I'll be honest, though, I don't really know what to expect with exec 0>&- and exec 0<&-.  When I call them in the terminal, it kills the terminal.

The surprising bit is that running this in xfce4-terminal

    ----- /tmp/temp-file-with-source-block-code -----
    ssh localhost "echo foo>foo_file"
    echo "bar" | tee /tmp/bar.txt
    -------------------------------------------------

    #+begin_example
    cat /tmp/temp-file-with-source-block-code.sh | bash -c bash
    #+end_example

does *not* echo bar (and does not create /tmp/bar.txt) yet it creates foo_file.  I get prompted for my password and then the second line doesn't execute.  Nothing prints to the console and no bar.txt is created.

This is the behavior Alain reports happening in Org (that I am unable to reproduce).  That is, the *reported behavior is the expected behavior* (assuming my analysis is correct).  However, according to the behavior I see when I run the block (fails to create the remote file and echoes "bar"), Org does the "wrong thing".  I can't account for this.

Anyway, Ihor's main point stands: a prompt does not work with non-session shell blocks.  The following returns exit code 1 (which means fail):

    #+begin_src bash :results output
    read -p "What? "
    #+end_src

As far as I can tell, though, that's not what prevents "bar" from being returned.  As far as I can reproduce, calling

    #+begin_src bash :results output
    ssh localhost "echo foo>foo_file"
    echo "bar"
    #+end_src

*does* give "bar" for results even though it shouldn't.

** Comment 2.
The second claim has nothing to do with Org Babel.  I was able to confirm it and provide the steps to reproduce.  I think it would make sense to report it upstream and let them decide if it's expected behavior.  I'm still happy to do that, but I need to step away from the keyboard :)



  parent reply	other threads:[~2023-11-17 22:09 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-25 11:17 bash source code block: problem after ssh commands Alain.Cochard
2023-10-25 15:12 ` Leo Butler
2023-10-25 16:14   ` Alain.Cochard
2023-10-25 16:47     ` Leo Butler
2023-10-25 16:59     ` yaxp
2023-10-26  8:44   ` Ihor Radchenko
2023-10-26 13:23     ` Alain.Cochard
2023-10-26 13:44       ` Ihor Radchenko
2023-10-27 18:26         ` Alain.Cochard
2023-10-28  5:22           ` Max Nikulin
2023-10-30 10:50           ` Bruno Barbier
2023-11-06 13:32             ` Ihor Radchenko
2023-11-06 18:25               ` Matt
2023-11-07  8:55                 ` Ihor Radchenko
2023-11-08 19:41                   ` Matt
2023-11-09 12:14                     ` Ihor Radchenko
2023-11-09 17:48                       ` Matt
2023-11-15 16:32                         ` Matt
2023-11-15 18:04                           ` Matt
2023-11-16  9:32                           ` Ihor Radchenko
2023-11-16 19:03                             ` Matt
2023-11-16 19:46                               ` Alain.Cochard
2023-11-16 20:54                                 ` Matt
2023-11-17  9:22                                   ` Ihor Radchenko
2023-11-17  9:55                                     ` Alain.Cochard
2023-11-17 10:17                                       ` Ihor Radchenko
2023-11-17 15:32                                         ` Leo Butler
2023-11-17 15:47                                         ` Bruno Barbier
2023-11-18 10:37                                           ` Ihor Radchenko
2023-11-21 19:01                                             ` Bruno Barbier
2023-11-22 17:06                                               ` Max Nikulin
2023-11-19  4:17                                           ` Non-emacs shell (Re: bash source code block: problem after ssh commands) Max Nikulin
2023-11-21 15:33                                             ` Bruno Barbier
2023-11-18  8:04                                         ` bash source code block: problem after ssh commands Max Nikulin
2023-11-18 10:43                                           ` Ihor Radchenko
2023-11-18 16:18                                             ` Max Nikulin
2023-11-17 22:07                                     ` Matt [this message]
2023-11-18  3:11                                       ` Forget about "bash -c bash file.sh" (Re: bash source code block: problem after ssh commands) Max Nikulin
2023-11-18  8:11                                         ` Matt
2023-11-18  8:29                                           ` Bruno Barbier
2023-11-18  8:43                                             ` Matt
2023-11-18  8:54                                               ` Bruno Barbier
2023-11-18  9:09                                                 ` Matt
2023-11-18  9:11                                                   ` Bruno Barbier
2023-11-18 10:47                                                   ` Ihor Radchenko
2023-11-18  8:19                                       ` bash source code block: problem after ssh commands Bruno Barbier
2023-11-18  9:02                                         ` Matt
2023-11-18 15:51                                       ` Matt
2023-10-26 14:44 ` Russell Adams
2023-10-27 11:47   ` Alain.Cochard
2023-11-06 18:01     ` Matt
2023-11-07  0:51       ` Alain.Cochard
2023-11-18  8:09 ` Max Nikulin
2023-11-18  8:36   ` Bruno Barbier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=18bdf538f2f.126bad4763316098.8581777358227217138@excalamus.com \
    --to=matt@excalamus.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=yantar92@posteo.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public 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).