1

System: Linux Mint 18.1 64-bit Cinnamon.


Objective: To define Bash aliases to launch various CLI and GUI text editors while opening a file in root mode from gnome-terminal emulator.


Progress

For example, the following aliases seem to work as expected:

For CLI, in this example I used Nano (official website):

alias sunano='sudo nano'

For GUI, in this example I used Xed (Wikipedia article):

alias suxed='sudo xed'

They both open a file as root.


Problem

I have an issue with gksudo in conjunction with sublime-text:

alias susubl='gksudo /opt/sublime_text/sublime_text'

Sometimes it works. It just does not do anything most of the time.

How do I debug such a thing with inconsistent behavior? It does not output anything. No error message or similar.


Question

gksudo has been deprecated in Debian and also no longer included in Ubuntu 18.04 Bionic, so let me re-formulate this question to a still valid one:

How to properly edit system files (as root) in GUI (and CLI) in Linux?

Properly in this context I define as safely in case, for instance, a power loss occurs during the file edit, another example could be lost SSH connection, etc.

  • I'm not sure how new the feature is but Sublime Text now prompts for root escalation when saving existing files. You still need to create new files from the command line though. – Annan Apr 23 at 14:52
5

You shouldn’t run an editor as root unless absolutely necessary, you should set sudoedit up appropriately. Then you can do

SUDO_EDITOR="/opt/sublime_text/sublime_text -w" sudoedit yourfile

sudoedit will check you’re allowed to do this, make a copy of the file that you can edit with changing ids, start your editor, and then, when the editor exits, copy the file back if it has been changed.

I’d suggest a function rather than an alias:

function susubl {
    export SUDO_EDITOR="/opt/sublime_text/sublime_text -w"
    sudoedit "$@"
}

although as Jeff Schaller pointed out, you can use env to put this in an alias and avoid changing your shell’s environment:

alias susubl='env SUDO_EDITOR="/opt/sublime_text/sublime_text -w" sudoedit'

The -w option ensures that the Sublime Text invocation waits until the files are closed before returning and letting sudoedit copy the files back.

1

Expanding on Stephen Kitt's answer

  1. Find out, on what path your editor is located, e.g.:

    $ which nano
    /usr/local/bin/nano
    

    As you can see, I use compiled nano, not the packaged version; no matter this can change from system/config to other system/config.

  2. The CLI text editors like vi or nano do not seem to have the wait option, so for my nano and vi one can write functions like this:

    # CLI
    sunano() { env SUDO_EDITOR='/usr/local/bin/nano' sudoedit "${@}"; }
    suvi()   { env SUDO_EDITOR='/usr/bin/vi' sudoedit "${@}"; }
    
  3. The GUI text editors, on the contrary, like Linux Mint's integrated xed, free programs like Visual Studio Code (code), or paid programs like Sublime Text (subl) all seem to have the wait option, and you need to use it in order to avoid the problem described in my question, you can use something similar to these functions:

    # GUI
    susubl() { env SUDO_EDITOR='/opt/sublime_text/sublime_text -w' sudoedit "${@}"; }
    sucode() { env SUDO_EDITOR='/usr/share/code/bin/code -w' sudoedit "${@}"; }
    suxed()  { env SUDO_EDITOR='/usr/bin/xed -w' sudoedit "${@}"; }
    

What the -w (--wait) option effectively does is, that the editor will wait on the terminal until you close it, thus waiting on close of the editor, enabling further actions to be planned and done on an editor close, in this instance to save the sudoedit changes. Normally, it would just free the terminal, and you would get a new prompt.

Imagine another useful usage for this:

code -w /home/vlastimil/.bash_aliases; . /home/vlastimil/.bash_aliases

Hopefully, with this example, I make myself clearer.


Generalized and POSIX-ly written, ready-to-use, function

You should, of course, compile your own list of favorited editors, these are my own, take it only as an example, and populate the list with yours.

# Text editing as root; The proper way through `sudoedit`.
sudoedit_run()
{
    [ ${#} -lt 3 ] &&
    {
        printf '%s\n' 'sudoedit_run(): Invalid number of arguments.' >&2
        return 1
    }
    editor_path=$( command -v "${1}" )
    [ -x "${editor_path}" ] ||
    {
        printf '%s\n' "sudoedit_run(): The path to '${1}' editor does not exist on this system." >&2
        return 1
    }
    editor_wait_option=${2}
    shift 2
    env SUDO_EDITOR="${editor_path} ${editor_wait_option}" sudoedit "${@}"
}
# shellcheck disable=SC2139
for cli_editor in vi nano
    do alias su${cli_editor}="sudoedit_run ${cli_editor} ''"
done
# shellcheck disable=SC2139
for gui_editor in code subl xed gedit
    do alias su${gui_editor}="sudoedit_run ${gui_editor} -w"
done
0

Different solution: I never edit system files directly, I make a copy somewhere(*), edit the copy (with my usual editor), and sudo cp when done.

(*) I have a directory for this, where all files are kept in one place:

  • naturally keeps a list of all the file that I have changed
  • easy to version
  • easy to backup
  • easy to transfer to another machine

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.