10

When I adb into a device with Cyanogenmod, I'm presented with a nice bash shell, color prompt, and bashrc. I don't see a symlink from /system/xbin/bash to /system/bin/sh. How do they set the default shell to bash instead of sh? I looked through rc files, but didn't find anything. I'd like to do the same on my Android build, which isn't Cyanogenmod.

Update

After re-installing from scratch with CM7, I'm taken to sh instead of bash. Now the question is how to set bash as default.

  • Vanilla CM7 (built from source) drops me at sh, not bash, when I use adb to connect. What build are you using? – eldarerathis Feb 10 '12 at 2:00
  • It's 7.1.0.1 for the ViewSonic G Tablet. I didn't build from sources though. – Ravi Feb 10 '12 at 2:37
7

When adb shell is executed, the Android side also launches adb which then executes /system/bin/sh -. This path is hard-coded in system/core/adb/services.c:

347 #if ADB_HOST
348 #define SHELL_COMMAND "/bin/sh"
349 #define ALTERNATE_SHELL_COMMAND ""
350 #else
351 #define SHELL_COMMAND "/system/bin/sh"
352 #define ALTERNATE_SHELL_COMMAND "/sbin/sh"
353 #endif

If you want to change this to bash, you will have to recompile it.

It is possible to execute some commands from file when running the interactive shell. As written in system/core/sh/main.c, sh - (note the - for interactive mode) reads from the following files (in this order):

  • /etc/profile
  • .profile (relative to current directory, this is /.profile for adb shell
  • $ENV (environment variable ENV should point to a file)

As /etc/ and / are read-only, the only way to get something loaded was by setting ENV. You can probably create a symlink from /etc/profile to /data/profile by mounting / read-write (exercise for the reader).

  • 1
    /etc is a symlink to the /system partition. I remounted that read-write and added /etc/profile but it does not get called by sh :( – Colin Oct 9 '14 at 3:28
5

I didn't have my Android with me right now to test, but with the Android Terminal Emulator if you go to the menu, you might be able to use the "Command line" or "Initial command" option.

enter image description here

  • Gee, I'll have to try that menu from my adb prompt. – mchid Apr 13 '16 at 3:24
3

This is an old question, but I was recently curious about this myself. I found a method that doesn't require recompiling adbd, however it does require su (I'm using Chainfire SuperSu 2.45).

Assuming bash is located at /system/bin/bash, and su is at /system/xbin/su, it's essentially something like this:

  1. adb shell (use an interactive shell. Invoking this process as a one-liner could cause ADB to cease working if there is a problem)
  2. mount -o remount,rw /system
  3. mv /system/bin/sh /system/bin/sh.bak
  4. echo -e '#!/system/bin/bash\n/system/xbin/su -mm -l -s /system/xbin/bash' > /system/bin/sh Note that your paths may differ; use which bash and which su to be sure.
  5. chmod 777 /system/bin/sh
  6. Test the shell before you exit: /system/bin/sh. If you get an error, fix the error or revert by restoring the backup: cp /system/bin/sh.bak /system/bin/sh.
  7. Optionally remount /system; most devices will do this automatically: mount -o remount,ro /system

And you're done.

Simply symlinking BASH to SH doesn't work because bash emulates SH when invoked this way.

However, having a look at strace, it does seem to look for a bashrc when a symlinked BASH is called as 'sh --login'. While this could conceivably be used to "chainload" shells via script, as mentioned above the way adbd invokes SH is hardcoded.

If there is a problem and you have removed (or moved) /system/bin/sh ADB wont have a shell to give you to fix the problem. If this happens, you have a few options:

  • Reboot into a recovery that has adbd (such as CWM or TWRP) and open an adb shell to it, to copy /system/bin/sh.bak over to /system/bin/sh again.
  • Use adb to copy the backup: adb root; adb remount; adb shell; adb pull /system/bin/sh.bak; adb push sh.bak /system/bin/sh Note that this won't work on all devices; some refuse to allow adb to remount /system rw in this way.
  • Use a terminal emulator that can be set to run a different shell; note that several will try /system/bin/sh first and force close.
0

On your PC, get a bash binary and overwrite /system/bin/sh. I have one here.

Feel free to copy this code:

git clone https://github.com/SuperDethByte/Bash-for-ARM.git        
cd Bash-for-ARM                
echo "Make sure your phone is plugged into your computer."          
sleep 5s                
echo "Remounting /system partition as r/w..."       
adb shell mount -o remount,rw /system          
echo "Making A Backup..."              
adb shell cp /system/bin/sh /system/bin/sh.bak         
echo "checking if backup was made..."          
if [ adb shell 'ls /system/bin/ | grep "sh.bak"' ]; then     
echo "pushing bash binary to android..."          
adb push bash /system/bin/sh       
echo "Remounting /system partition as r/o..."         
adb shell mount -o remount,ro /system          
echo "DONE"        
else         
echo "Backup Failed"           
echo "Remounting /system partition as r/o..."      
adb shell mount -o remount,ro /system     
fi   

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.