Ssh en Rescue mode

Bonjour,

Je rencontre un soucis sur un serveur SLES9 distant pour lequel je souhaite accéder en ssh via le mode rescue. En effet, l'OS ayant quelque peu crashé, je n'ai plus la possibilité de le faire booter.

Existe t'il donc une solution pour accéder en ssh sur le serveur qui est en rescue mode?

Merci d'avance,

3 réponses

  1. Modérateur
    En fait tout dépend de ce que le rescue mode te permet de faire. Si tu peux accéder à la machine en local, déjà on part bien, car tu vas pouvoir lancer le service ssh et par la suite y accéder depuis le réseau.

    Version courte

    A priori le démon sshd (le serveur ssh) est instancié via le script /etc/init.d/ssh ou nom proche. On peut instancier ce script directement par la commande suivante (en root) :

    /etc/init.d/ssh start


    ... ou mieux (mais pas toujours possible si la distribution est vieille par exemple) :

    service ssh start


    (ce qui est équivalent soit dit en passant). Après quoi le serveur ssh devrait être accessible.

    Version longue

    En fait il faut bien voir que démarrer en rescue mode ou en normal mode ne consiste (une fois le kernel chargé) qu'à démarrer sur un runlevel différent. Un runlevel correspond à un état de la machine (arrêt, rescue, normal, ...., reboot) numéroté de 0 à 6. L'un d'eux (le 2 sous debian) est le runlevel par défaut. Certains sont standardisés (0 pour l'arrêt (halt), 1 pour le mode simple utilisateur (recovery), et 6 pour le reboot).

    En fonction du runlevel sur lequel on démarre, certaines lignes de /etc/inittab sont évaluées ou non. Pour les distributions plus récente, note que ce fichier n'existe plus mais le principe reste le même. Bref, ce fichier instancie le script shell /etc/init.d/rc et lui passe le runlevel en paramètre.

    Extrait de /etc/inittab

    ...
    # /etc/init.d executes the S and K scripts upon change
    # of runlevel.
    #
    # Runlevel 0 is halt.
    # Runlevel 1 is single-user.
    # Runlevels 2-5 are multi-user.
    # Runlevel 6 is reboot.
    
    l0:0:wait:/etc/init.d/rc 0
    l1:1:wait:/etc/init.d/rc 1
    l2:2:wait:/etc/init.d/rc 2
    l3:3:wait:/etc/init.d/rc 3
    l4:4:wait:/etc/init.d/rc 4
    l5:5:wait:/etc/init.d/rc 5
    l6:6:wait:/etc/init.d/rc 6
    ...


    Celui-ci instancie en cascade (soit start, soit stop) un ou plusieurs services. Rappelons que les scripts associés aux services sont tous dans /etc/init.d (et c'est pour ca que ssh se lance par /etc/init.d/ssh).

    Pour savoir ce qu'il doit lancer ou éteindre, le script /etc/init.d/rc examine les liens symboliques établis dans /etc/rcX.d ou X est à remplacer par le numéro du runlevel dans lequel on bascule. C'est lien commence par K (kill) ou S (start) selon les services qui doivent être coupés ou démarrés dans tel ou tel runlevel.

    Ainsi /etc/rc0.d (arrêt) et /etc/rc6.d (reboot) contiennent uniquement des liens K (on éteint tout), tandis que /etc/rc1.d contient quelques S et /etc/rc2.d plus de liens S (on démarre plus de service en mode normal qu'en recovery).

    Bref tu l'auras compris, démarrer en recovery mode ne revient qu'à lancer moins de service, mais on peut tout à fait les instancier a posteriori. C'est le rôle de la commande :

    /etc/init.d/ssh start
    service ssh start


    (qui est un script shell et que tu peux regarder avec ton éditeur texte favori). Note que tous les scripts de /etc/init.d supporte le passage des mêmes options (start, stop, restart, ...).

    On peut même basculer la machine dans un autre runlevel (voir commandes init, halt et reboot) qui, tu l'auras compris consistent notamment à invoquer les scripts associés aux différents services.

    Bonne chance
    1. Merci mamiemando pour ta réponse précise.

      Le soucis est que lorsque je boot sur le mode rescue (via le CD de la SLES9), dans /etc/init.d, je n'ai pas le service ssh ou sshd de disponible. Je peut mettre en place une IP sur le serveur avec "ifconfig eth0 XX.XX.XX.XX", ce dernier devient donc visible sur le réseau (ping OK) mais le ssh ne fonctionne pas.

      Cordialement
      1. Modérateur
        Forcément... si tu ne lances pas de démon ssh, pas de ssh :) Il devrait apparaître (s'il est lancé) avec un ps :

        (mando@aldur) (~) $ ps aux | grep sshd
        root      1781  0.0  0.0   5492   944 ?        Ss   18:47   0:00 /usr/sbin/sshd
        mando     2349  0.0  0.0   3320   812 pts/1    S+   18:56   0:00 grep sshd


        Rien ne t'empêche d'instancier directement sshd par cette commande (en root) :

        /usr/sbin/sshd


        ... mais a priori on fait plutôt ça via un service (donc le fameux /etc/init.d/ssh start).

        Au pire si tu veux vraiment passer par un script, voici les fichiers utilisés sous debian (à préparer sur clé usb par exemple)

        /lib/lsb/init-functions

        # /lib/lsb/init-functions for Debian -*- shell-script -*-
        #
        #Copyright (c) 2002-08 Chris Lawrence
        #All rights reserved.
        #
        #Redistribution and use in source and binary forms, with or without
        #modification, are permitted provided that the following conditions
        #are met:
        #1. Redistributions of source code must retain the above copyright
        #   notice, this list of conditions and the following disclaimer.
        #2. Redistributions in binary form must reproduce the above copyright
        #   notice, this list of conditions and the following disclaimer in the
        #   documentation and/or other materials provided with the distribution.
        #3. Neither the name of the author nor the names of other contributors
        #   may be used to endorse or promote products derived from this software
        #   without specific prior written permission.
        #
        #THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
        #IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        #WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        #ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
        #LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        #CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        #SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
        #BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        #WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
        #OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
        #EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        
        start_daemon () {
            local force nice pidfile exec i args
            force=0
            nice=0
            pidfile=/dev/null
        
            OPTIND=1
            while getopts fn:p: opt ; do
                case "$opt" in
                    f)  force=1;;
                    n)  nice="$OPTARG";;
                    p)  pidfile="$OPTARG";;
                esac
            done
            
            shift $(($OPTIND - 1))
            if [ "$1" = '--' ]; then
                shift
            fi
        
            exec="$1"; shift
        
            args="--start --nicelevel $nice --quiet --oknodo"
            if [ $force = 1 ]; then
                /sbin/start-stop-daemon $args --chdir "$PWD" --startas $exec --pidfile /dev/null -- "$@"
            elif [ $pidfile ]; then
                /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec --oknodo --pidfile "$pidfile" -- "$@"
            else
                /sbin/start-stop-daemon $args --chdir "$PWD" --exec $exec -- "$@"
            fi
        }
        
        pidofproc () {
            local pidfile line i pids= status specified pid
            pidfile=
            specified=
            
            OPTIND=1
            while getopts p: opt ; do
                case "$opt" in
                    p)  pidfile="$OPTARG"; specified=1;;
                esac
            done
            shift $(($OPTIND - 1))
        
            base=${1##*/}
            if [ ! "$specified" ]; then
                pidfile="/var/run/$base.pid"
            fi
        
            if [ -n "${pidfile:-}" -a -r "$pidfile" ]; then
                read pid < "$pidfile"
                if [ -n "${pid:-}" ]; then
                    if $(kill -0 "${pid:-}" 2> /dev/null); then
                        echo "$pid"
                        return 0
                    elif ps "${pid:-}" >/dev/null 2>&1; then
                        echo "$pid"
                        return 0 # program is running, but not owned by this user
                    else
                        return 1 # program is dead and /var/run pid file exists
                    fi
                fi
            fi
            if [ -x /bin/pidof -a ! "$specified" ]; then
                status="0"
                /bin/pidof -o %PPID -x $1 || status="$?"
                if [ "$status" = 1 ]; then
                    return 3 # program is not running
                fi
                return 0
            fi
            return 4 # Unable to determine status
        }
        
        # start-stop-daemon uses the same algorithm as "pidofproc" above.
        killproc () {
            local pidfile sig status base i name_param is_term_sig
            pidfile=
            name_param=
            is_term_sig=no
        
            OPTIND=1
            while getopts p: opt ; do
                case "$opt" in
                    p)  pidfile="$OPTARG";;
                esac
            done
            shift $(($OPTIND - 1))
        
            base=${1##*/}
            if [ ! $pidfile ]; then
                name_param="--name $base --pidfile /var/run/$base.pid"
            else
                name_param="--pidfile $pidfile"
            fi
        
            sig=$(echo ${2:-} | sed -e 's/^-\(.*\)/\1/')
            sig=$(echo $sig | sed -e 's/^SIG\(.*\)/\1/')
            if [ -z "$sig" -o "$sig" = 15 -o "$sig" = TERM ]; then
                is_term_sig=yes
            fi
            status=0
            if [ ! "$is_term_sig" = yes ]; then
                if [ -n "$sig" ]; then
                    /sbin/start-stop-daemon --stop --signal "$sig" --quiet $name_param || status="$?"
                else
                    /sbin/start-stop-daemon --stop --quiet $name_param || status="$?"
                fi
            else
                /sbin/start-stop-daemon --stop --quiet --oknodo $name_param || status="$?"
            fi
            if [ "$status" = 1 ]; then
                if [ -n "$sig" ]; then
                    return 0
                fi
                return 3 # program is not running
            fi
        
            if [ "$status" = 0 -a "$is_term_sig" = yes -a "$pidfile" ]; then
                pidofproc -p "$pidfile" "$1" >/dev/null || rm -f "$pidfile"
            fi
            return 0
        }
        
        # Return LSB status
        status_of_proc () {
            local pidfile daemon name status
        
            pidfile=
            OPTIND=1
            while getopts p: opt ; do
                case "$opt" in
                    p)  pidfile="$OPTARG";;
                esac
            done
            shift $(($OPTIND - 1))
        
            if [ -n "$pidfile" ]; then
                pidfile="-p $pidfile"
            fi
            daemon="$1"
            name="$2"
        
            status="0"
            pidofproc $pidfile $daemon >/dev/null || status="$?"
            if [ "$status" = 0 ]; then
                log_success_msg "$name is running"
                return 0
            elif [ "$status" = 4 ]; then
                log_failure_msg "could not access PID file for $name"
                return $status
            else
                log_failure_msg "$name is not running"
                return $status
            fi
        }
        
        log_use_fancy_output () {
            TPUT=/usr/bin/tput
            EXPR=/usr/bin/expr
            if [ -t 1 ] && [ "x${TERM:-}" != "x" ] && [ "x${TERM:-}" != "xdumb" ] && [ -x $TPUT ] && [ -x $EXPR ] && $TPUT hpa 60 >/dev/null 2>&1 && $TPUT setaf 1 >/dev/null 2>&1; then
                [ -z $FANCYTTY ] && FANCYTTY=1 || true
            else
                FANCYTTY=0
            fi
            case "$FANCYTTY" in
                1|Y|yes|true)   true;;
                *)              false;;
            esac
        }
        
        log_success_msg () {
            if [ -n "${1:-}" ]; then
                log_begin_msg $@
            fi
            log_end_msg 0
        }
        
        log_failure_msg () {
            if [ -n "${1:-}" ]; then
                log_begin_msg $@ "..."
            fi
            log_end_msg 1 || true
        }
        
        log_warning_msg () {
            if [ -n "${1:-}" ]; then
                log_begin_msg $@ "..."
            fi
            log_end_msg 255 || true
        }
        
        #
        # NON-LSB HELPER FUNCTIONS
        #
        # int get_lsb_header_val (char *scriptpathname, char *key)
        get_lsb_header_val () {
                if [ ! -f "$1" ] || [ -z "${2:-}" ]; then
                        return 1
                fi
                LSB_S="### BEGIN INIT INFO"
                LSB_E="### END INIT INFO"
                sed -n "/$LSB_S/,/$LSB_E/ s/# $2: \(.*\)/\1/p" $1
        }
        
        # int log_begin_message (char *message)
        log_begin_msg () {
            if [ -z "${1:-}" ]; then
                return 1
            fi
            echo -n "$@"
        }
        
        # Sample usage:
        # log_daemon_msg "Starting GNOME Login Manager" "gdm"
        #
        # On Debian, would output "Starting GNOME Login Manager: gdm"
        # On Ubuntu, would output " * Starting GNOME Login Manager..."
        #
        # If the second argument is omitted, logging suitable for use with
        # log_progress_msg() is used:
        #
        # log_daemon_msg "Starting remote filesystem services"
        #
        # On Debian, would output "Starting remote filesystem services:"
        # On Ubuntu, would output " * Starting remote filesystem services..."
        
        log_daemon_msg () {
            if [ -z "${1:-}" ]; then
                return 1
            fi
            log_daemon_msg_pre "$@"
        
            if [ -z "${2:-}" ]; then
                echo -n "$1:"
                return
            fi
            
            echo -n "$1: $2"
            log_daemon_msg_post "$@"
        }
        
        # #319739
        #
        # Per policy docs:
        #
        #     log_daemon_msg "Starting remote file system services"
        #     log_progress_msg "nfsd"; start-stop-daemon --start --quiet nfsd
        #     log_progress_msg "mountd"; start-stop-daemon --start --quiet mountd
        #     log_progress_msg "ugidd"; start-stop-daemon --start --quiet ugidd
        #     log_end_msg 0
        #
        # You could also do something fancy with log_end_msg here based on the
        # return values of start-stop-daemon; this is left as an exercise for
        # the reader...
        #
        # On Ubuntu, one would expect log_progress_msg to be a no-op.
        log_progress_msg () {
            if [ -z "${1:-}" ]; then
                return 1
            fi
            echo -n " $@"
        }
        
        
        # int log_end_message (int exitstatus)
        log_end_msg () {
            # If no arguments were passed, return
            if [ -z "${1:-}" ]; then
                return 1
            fi
        
            retval=$1
        
            log_end_msg_pre "$@"
        
            # Only do the fancy stuff if we have an appropriate terminal
            # and if /usr is already mounted
            if log_use_fancy_output; then
                RED='$TPUT setaf 1'
                YELLOW='$TPUT setaf 3'
                NORMAL='$TPUT op'
            else
                RED=''
                YELLOW=''
                NORMAL=''
            fi
        
            if [ $1 -eq 0 ]; then
                echo "."
            elif [ $1 -eq 255 ]; then
                /bin/echo -e " ${YELLOW}(warning).${NORMAL}"
            else
                /bin/echo -e " ${RED}failed!${NORMAL}"
            fi
            log_end_msg_post "$@"
            return $retval
        }
        
        log_action_msg () {
            echo "$@."
        }
        
        log_action_begin_msg () {
            echo -n "$@..."
        }
        
        log_action_cont_msg () {
            echo -n "$@..."
        }
        
        log_action_end_msg () {
            log_action_end_msg_pre "$@"
            if [ -z "${2:-}" ]; then
                end="."
            else
                end=" ($2)."
            fi
        
            if [ $1 -eq 0 ]; then
                echo "done${end}"
            else
                if log_use_fancy_output; then
                    RED='$TPUT setaf 1'
                    NORMAL='$TPUT op'
                    /bin/echo -e "${RED}failed${end}${NORMAL}"
                else
                    echo "failed${end}"
                fi
            fi
            log_action_end_msg_post "$@"
        }
        
        # Hooks for /etc/lsb-base-logging.sh
        log_daemon_msg_pre () { :; }
        log_daemon_msg_post () { :; }
        log_end_msg_pre () { :; }
        log_end_msg_post () { :; }
        log_action_end_msg_pre () { :; }
        log_action_end_msg_post () { :; }
        
        FANCYTTY=
        [ -e /etc/lsb-base-logging.sh ] && . /etc/lsb-base-logging.sh || true


        /etc/default/ssh

        # Default settings for openssh-server. This file is sourced by /bin/sh from
        # /etc/init.d/ssh.
        
        # Options to pass to sshd
        SSHD_OPTS=


        /etc/init.d/ssh

        #! /bin/sh
        
        ### BEGIN INIT INFO
        # Provides:             sshd
        # Required-Start:       $remote_fs $syslog
        # Required-Stop:        $remote_fs $syslog
        # Default-Start:        2 3 4 5
        # Default-Stop:
        # Short-Description:    OpenBSD Secure Shell server
        ### END INIT INFO
        
        set -e
        
        # /etc/init.d/ssh: start and stop the OpenBSD "secure shell(tm)" daemon
        
        test -x /usr/sbin/sshd || exit 0
        ( /usr/sbin/sshd -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0
        
        umask 022
        
        if test -f /etc/default/ssh; then
            . /etc/default/ssh
        fi
        
        . /lib/lsb/init-functions
        
        if [ -n "$2" ]; then
            SSHD_OPTS="$SSHD_OPTS $2"
        fi
        
        # Are we running from init?
        run_by_init() {
            ([ "$previous" ] && [ "$runlevel" ]) || [ "$runlevel" = S ]
        }
        
        check_for_no_start() {
            # forget it if we're trying to start, and /etc/ssh/sshd_not_to_be_run exists
            if [ -e /etc/ssh/sshd_not_to_be_run ]; then 
                if [ "$1" = log_end_msg ]; then
                    log_end_msg 0
                fi
                if ! run_by_init; then
                    log_action_msg "OpenBSD Secure Shell server not in use (/etc/ssh/sshd_not_to_be_run)"
                fi
                exit 0
            fi
        }
        
        check_dev_null() {
            if [ ! -c /dev/null ]; then
                if [ "$1" = log_end_msg ]; then
                    log_end_msg 1 || true
                fi
                if ! run_by_init; then
                    log_action_msg "/dev/null is not a character device!"
                fi
                exit 1
            fi
        }
        
        check_privsep_dir() {
            # Create the PrivSep empty dir if necessary
            if [ ! -d /var/run/sshd ]; then
                mkdir /var/run/sshd
                chmod 0755 /var/run/sshd
            fi
        }
        
        check_config() {
            if [ ! -e /etc/ssh/sshd_not_to_be_run ]; then
                /usr/sbin/sshd $SSHD_OPTS -t || exit 1
            fi
        }
        
        export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
        
        case "$1" in
          start)
                check_privsep_dir
                check_for_no_start
                check_dev_null
                log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd"
                if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
                    log_end_msg 0
                else
                    log_end_msg 1
                fi
                ;;
          stop)
                log_daemon_msg "Stopping OpenBSD Secure Shell server" "sshd"
                if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid; then
                    log_end_msg 0
                else
                    log_end_msg 1
                fi
                ;;
        
          reload|force-reload)
                check_for_no_start
                check_config
                log_daemon_msg "Reloading OpenBSD Secure Shell server's configuration" "sshd"
                if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd; then
                    log_end_msg 0
                else
                    log_end_msg 1
                fi
                ;;
        
          restart)
                check_privsep_dir
                check_config
                log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"
                start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sshd.pid
                check_for_no_start log_end_msg
                check_dev_null log_end_msg
                if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
                    log_end_msg 0
                else
                    log_end_msg 1
                fi
                ;;
        
          try-restart)
                check_privsep_dir
                check_config
                log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"
                set +e
                start-stop-daemon --stop --quiet --retry 30 --pidfile /var/run/sshd.pid
                RET="$?"
                set -e
                case $RET in
                    0)
                        # old daemon stopped
                        check_for_no_start log_end_msg
                        check_dev_null log_end_msg
                        if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
                            log_end_msg 0
                        else
                            log_end_msg 1
                        fi
                        ;;
                    1)
                        # daemon not running
                        log_progress_msg "(not running)"
                        log_end_msg 0
                        ;;
                    *)
                        # failed to stop
                        log_progress_msg "(failed to stop)"
                        log_end_msg 1
                        ;;
                esac
                ;;
        
          status)
                status_of_proc -p /var/run/sshd.pid /usr/sbin/sshd sshd && exit 0 || exit $?
                ;;
        
          *)
                log_action_msg "Usage: /etc/init.d/ssh {start|stop|reload|force-reload|restart|try-restart|status}"
                exit 1
        esac
        
        exit 0


        ... mais je ne sais pas dans quelle mesure il marchera chez toi. Le plus simple est peut-être d'instancier directement sshd à la main.

        Bonne chance