2

I have Fedora 20 and Gnome3 classic, and I am trying to use the CTRL/ALT/Fn terminal windows. When I want to edit a file with emacs I use the following script so that my Hints file is automatically displayed and emacs is run as a backgound job. This works fine in the non-login terminal from Gnome desktop applications, but in the log-in terminal I get error messages: (obtained by redirection with '&> e' in the CTL/ALT/F2 window)

    home/Harry/bin/emx: line 4: t: Permission denied  
    +---------------------------------------------------+  
    | EmacsHints.txt found and displayed                |  
    | Usage: ./emx <filename> ..                        |  
    |   .. Opens EmacsHints.txt and <filename> in emacs |  
    +---------------------------------------------------+
    emacs: standard input is not a tty

Please can someone explain these, and tell me how to avoid them and use the emx script (no doubt modified) successfully in both log-in and non log-in terminals?

Revised version of my emx script, I have include my notes and debugging stuff:

#!/bin/sh
emxhn="EmacsHints.txt"
emxhf="/home/Harry/emacs/$emxhn"
ps aux | grep $emxhn > t
T=`wc -l t` # no spaces allowed between T and = and value
# echo $T
wc -l t > t1
T=`awk '$1' t1`
# echo $T

echo "+---------------------------------------------------+"

# In the test "" needed round $T else it is split into two commands ..
# .. so are the spaces after [ and before ]
# could be if ( [...] ) then or if [...] ; then 
if [ "$T" = "2 t" ]; then 
#  echo "+----------------------------------------------+"
 echo "| $emxhn already present"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \  "|"
else
 emacs $emxhf &
 echo "| $emxhn found and displayed"\ \ \ \ \ \ \ \ \ \ \ \ \ \ \  "|"
fi

if [ "$#" = "1" ]; then
 emacs $1 &
else
 echo "| Usage: ./emx <filename> .." \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \  "|"
 echo "|" \   ".. Opens $emxhn and <filename> in emacs" "|"
fi

  echo "+---------------------------------------------------+"

Yes, I see, I have fallen into the X-Y trap, asking X when I should have asked Y, so here's Y

I use emacs a lot but not all the time, and I also have a Hints file, in which I note how to do the tasks I encounter, and I like to have these Hints available while I am using emacs. I tried to automate this so that whenever I start emacs, if the Hints are not already there, then the file is opened as well. That script was my attempt to do so, and has been ok while I have run emacs from a non-login terminal within my Gnome3 classic style GUI. Trying it in a log-in terminal with CTL/ALT/F2 gave the error messages quoted.

I have used and loved Unix and Fedora Linux for many years, but obviously there's still an awful lot more to learn.

  • Very sorry, had a Senior Moment there. I got the wrong version of my script into the original question, now corrected. The line that gave the /home/Harry/bin/emx: line 4: t: Permission denied was the present line 4: ps aux | grep $emxhn > t – Harry Weston May 10 '14 at 15:18
3

Below, I analyse your script. But having done that, I think the answer to the question you should have asked is:

  • Run emacs --daemon from your .profile. This creates a background instance of Emacs.
  • Run emacsclient FILENAME to open a file in Emacs. This creates a new window (either an X11 window, or a window using the current terminal).
  • Load the EmacsHints file in your Emacs startup file: put (find-file "/home/Harry/emacs/EmacsHints.txt") in your .emacs.

We can't tell for sure why you're getting t: Permission denied, since you didn't post the script that generated this error (the script you posted has a comment on line 4). But you're creating a temporary file in the current directory; that's a bad idea in all circumstances, and probably isn't working when you don't have permission to write the current directory.

If you need to create a temporary file, use mktemp. However, here, temporary files are an unnecessary complication: use command substitution to store the output of the commands into a variable.

#!/bin/sh
ps_lines=$(ps aux | grep EmacsHints)
line_count=$(echo "$ps_lines" | wc -l)
T=$(echo "$line_count" | awk '$1')
if [ "$T" = "2" ]; then …

All of this in turn is awfully complicated — just pipe the output of grep into wc, and the awk step isn't doing anything useful.

if [ "$(ps aux | grep EmacsHints | wc -l)" = 2 ]; then …

Furthermore, your test is unreliable: when the EmacsHints file is open, sometimes ps will return one line containing EmacsHints, sometimes two: it depends on the timing of the ps and grep processes. Instead of building your own (which isn't working), use tools dedicated for this purpose: pidof or pgrep.

#!/bin/sh
if pgrep -f 'EmacsHints\.txt' >/dev/null; then …

Voilà! Simpler, and it actually works.

Well, it mostly works. If you open the EmacsHints file in Emacs without specifying it on the command line, this won't be detected. I'd offer a better solution, but I don't understand what you're trying to accomplish. If you always want to have the EmacsHints file open in Emacs, open it from your .emacs.

Emacs is a bit slow to start, but many users (including me) set it up to run when you log in and then never exit it. Run emacs --daemon from your .profile. To open a file in the existing Emacs instance, call emacsclient.

Regarding “standard input is not a tty”, you can run Emacs in the background only if it's opening a GUI window. If you're running Emacs in the terminal, it has to be in the foreground, otherwise it can't access the terminal. If you want to run Emacs in the background only in X:

if [ -n "$DISPLAY" ]; then
  emacs "$1" &
else
  emacs "$1"
fi

By the way, in a shell script, always put double quotes around variable and command substitutions: "$1", "$foo", "$(somecommand)", etc. When the substitution isn't inside double quotes, the value is interpreted not as a string but as a list of glob patterns. This issue typically manifests itself with scripts that fail on file names containing spaces. If you don't understand what all that means, just use double quotes.

Or you could just use emacsclient.

  • What a brilliant answer, Gilles, albeit a bit severe to an ageing newbie. I will study this and learn from it. Thank you very much for the time and trouble you took to compose it. – Harry Weston May 10 '14 at 14:34
0

Regarding this message:

emx: line 4: t: permission denied

The first is telling you that your command:

ps aux | grep EmacsHints > t

doesn't have permissions to write the file t to whatever directory it happens to be in when run. Better to specify a full path, I'd suggest using /tmp/t like so:

ps aux | grep EmacsHints > /tmp/t

The other message:

emacs: standard input is not a tty

Is telling you that the script does not have access to a TTY to display emacs. In order to run a tool such as emacs or vim in this manner you'll often ties need to have access to a TTY device so that you can get access to its STDIN and STDOUT.

If you're desperate or don't care about the lack of STDIN/STDOUT you can create a new one within your script like so:

emacs < $(tty) > $(tty)

There are other methods to deal with this, see this SO Q&A titled: How do I launch an editor from a shell script?.

  • This looks like the answer I need, but it's late into the night here in UK, so I will look into it tomorrow. Thank you – Harry Weston May 9 '14 at 22:00
  • The second part of your answer misses the point. Redirection isn't going to help, the core problem is that emacs needs to be run in the foreground when using a terminal interface. Plus, the whole script is a mess. – Gilles May 10 '14 at 11:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.