Messed up my .bash_profile remotely, can't ssh back in

7,234

Solution 1

As described here you can use

ssh -t user@host bash --noprofile

in fact, as @JoL suggests, you don't even need the --noprofile, since when ssh executes bash as just another command, it's not considered a login shell. Running ssh -t user@host bash will only read the RC files; and running ssh -t user@host bash --norc will not read even those.

Solution 2

Try to SSH and run sh instead of bash, e.g.

ssh user@host sh

Then rename (mv) or edit the broken file (ex/vi).

Solution 3

Run ssh -t host vi .bash_profile (or the editor of you choice in place of vi) and fix your .bash_profile.

(The -t option may not be needed, depending on which editor you choose.)

If you know exactly what needs to be fixed, you may be able to fix it non-interactively. For example, something like

printf 's/exec foo/. foo/\nwq\n' ssh host ed .bash_profile

Solution 4

If only ~/.bash_profile is messed up, see the other answers for fixing it. The rest of this answer elaborates on fixing all (other) login scripts.

If you are unlucky enough that you have echo Bad luck; exit 42 in the beginning of both your ~/.bashrc and ~/.bash_profile, and you have /bin/bash as your login shell, and ssh root@host doesn't work either, then its unlikely that you are able to fix it remotely. That's because sshd will insist on running your login shell, and the first /bin/bash will read either ~/.bashrc or ~/.bash_profile, and specifying bash --norc --noprofile is too late, because the /bin/bash run by sshd doesn't have these flags, no matter what you specify in the ssh command-line.

If you've messed up only ~/.bashrc, then run this to fix it:

echo mv -f .bashrc .bashrc.mess | ssh host

If you've messed up only ~/.bash_profile and/or ~/.profile and/or ~/.bash_login, then run this to fix it:

ssh host 'mv -f .bash_profile .bash_profile.mess; mv -f .profile .profile.mess; mv -f .bash_login .bash_login.mess'

After the fix, you can do ssh host as usual, and clean up the login script files in your favorite editor or using scp, sftp or rsync to transfer files and editing them locally.

Share:
7,234
einpoklum
Author by

einpoklum

Made my way from the Olympus of Complexity Theory, Probabilistic Combinatorics and Property Testing to the down-to-earth domain of Heterogeneous and GPU Computing, and now I'm hoping to bring the gospel of GPU and massive-regularized parallelism to DBMS architectures. I've post-doc'ed at the DB architecture group in CWI Amsterdam to do (some of) that. I subscribe to most of Michael Richter's critique of StackOverflow; you might want to take the time to read it. If you listen closely you can hear me muttering "Why am I not socratic again already?"

Updated on September 18, 2022

Comments

  • einpoklum
    einpoklum almost 2 years

    I'm using a GNU/Linux system remotely, via SSH.

    I mistakenly added something into my $HOME/.bash_profile scriot which causes an error. (To be specific: I added an exec foo command instead of . foo, applied to another bash script without execution permissions, which results in an error.)

    Now I can't seem to SSH, SCP or SFTP into my machine: bash, my login shell, tries to run the exec foo command, gets the error and throws me out! I don't have any other account I can access remotely.

    Is there something I can do to restore access to the system?

    Additional details:

    • Most ports other than for SSH are unavailable since the machine is behind a firewall.
    • It's a Devuan 3 ASCII (~= Debian 10 Beowulf) system.
  • einpoklum
    einpoklum over 4 years
    I +1'ed you, but it's more convenient to have bash then just plain sh, like @styrofoamfly suggests...
  • chepner
    chepner over 4 years
    Given that you aren't really going to do anything except run an editor to fix .bash_profile one you are logged in, I don't see how it matters what shell features are available.
  • spuck
    spuck over 4 years
    This might work, but you can't count on "sh" actually being a different shell. For example on this Ubuntu box, /bin/sh is a symlink to /bin/dash.
  • Kilian Foth
    Kilian Foth over 4 years
    @spuck sh might be the same binary as bash, but it will still change its behaviour when invoked as "sh" (including not reading Bash-specific files) for exactly this reason.
  • pts
    pts over 4 years
    For beginners who don't know vi, nano, nano-tiny or mcedit are convenient choices. (These editors are not always installed, but it's worth a try.)
  • einpoklum
    einpoklum over 4 years
    So, this will work, but you're over-complicating the explanation and eventually suggesting a slight variation on existing answers.
  • pts
    pts over 4 years
    @einpoklum-reinstateMonica: My answer adds the following over existing answers: 1. What happens if all login scripts are broken? 2. A different fix is needed depending on which login script is broken. 3. Provides fix for a broken ~/.bashrc . All of this can be relevant for future users who find this question. If you have a way to provide all this additional information and explanation in a simpler way, please suggest an edit.
  • pts
    pts over 4 years
    @einpoklum-reinstateMonica: 4. Not all users are comfortable running a text editor within an SSH session. This answer provides fixes avoiding that.
  • einpoklum
    einpoklum over 4 years
    1. I didn't ask about "all login scripts". 2. bash --noprofile should be ok., because... 3. When bash is a login shell it doesn't run rc files anyway. Finally, the bash run by sshd is just a command - you can choose the flags you like.
  • pts
    pts over 4 years
    1. StackExchange is not only for helping the OP, but also for helping anyone having a similar problem in the future, finding this question later. 2. bash --noprofile is a working fix only if ~/.bashrc is not messed up. 3. Correct. Finally, ssh -t host bash --noprofile runs 2 instances of bash: sshd runs /bin/bash -c 'bash --noprofile'. Thus it won't work if ~/.bashrc (sourced by the 1st bash) is messed up, no matter what flags are specified for the 2nd bash, which never gets run.
  • pts
    pts over 4 years
    @einpoklum-reinstateMonica: I'm happy that you have many fixes to choose from, and I'm happy that with my answer I provided value for users who have other login scripts messed up, and/or who are not comfortable running a text editor within an SSH session.
  • einpoklum
    einpoklum over 4 years
    Other answers already provide solutions for those cases, actually.
  • JoL
    JoL over 4 years
    You don't need --noprofile. ssh -t user@host bash already doesn't read the profile. The reason is because the profile is only read for "interactive login shells", and by doing ssh -t user@host bash you have a login non-interactive shell invoking a non-login interactive shell, so neither reads it.
  • pts
    pts over 4 years
    @einpoklum-reinstateMonica: I disagree with the opinion that other answers provide solutions for all those cases this answer provides a solution for. Examples (which I already mentioned several times, but I repeat it here for clarity): 2. A different fix is needed depending on which login script is broken. 3. Provides fix for a broken ~/.bashrc . 4. Not all users are comfortable running a text editor within an SSH session. This answer provides fixes avoiding that. (We can argue if ed in another answer is a viable solution for those users, I think it isn't.)
  • einpoklum
    einpoklum over 4 years
    @JoL: Please go ahead and edit the answer to reflect that.
  • JoL
    JoL over 4 years
    @einpoklum-reinstateMonica Seems like you beat me to it. However, you miswrote the option name as --newprofile. Also, "since when ssh executes bash as just another command, it's not considered a login shell" is slightly inaccurate. It's probably pedantic of me, but the bash that ssh executes is a login shell. It's the bash that bash executes that is not. The process hierarchy is sshd -> bash (login non-interactive) -> bash (non-login interactive).