4

Lately I've been playing around with .sh scripting in Android. At first I used BusyBox and it's integrated scripting utility, though I quickly realised that coding on the phone isn't the best, so I switched over to my desktop and started using ADB to push my scripts to my device. It all worked well for about two weeks, until recently the exact same scripts that used to work perfectly, tell me some : not found[0]: syntax error: '{ Error. I've copied the exact same code from my script and used BusyBox to create it for me, and that way it works just fine. So the code is fine.

After some digging, I think it's either because of permissions, because of encoding possibly, or also because of the location of the scripts. I've tried many different locations (because I want to be able to run the scripts without root), and ended up choosing /storage/emulated/0. If I understood correctly, this is a symlink to the internal storage, which is read/write-able without root. But maybe sometimes executable and sometimes not? I don't know.

So my question is as following: What is the best location on an Android Device to run scripts without root from? Preferably a path that works on any android device.

Info:

  • Rooted Samsung S7 SM-G930F
  • Android 8.0.0
  • I'm using #!/system/bin/sh inside the .sh files
  • I'm running the scripts with sh script.sh
  • When trying to run it as an executable ./script.sh, I get a Permission denied error. With or without root.

PS: And if anyone has a clue to why the exact same scripts stopped working out of nowhere, I'd be happy to know!

UPDATE: Thanks to @IrfanLatif, I've managed to fix the : not found[0]: syntax error: '{ Error! I was using Visual Studio Code as my editor for the scripts, which was saving them with the End of Line Sequence CRLF, which Android doesn't like. For an easy fix, just change your Line Endings to LF, problem solved. Check the comments out for more info.

4
  • 2
    @IrfanLatif Yup, that was exactly the case. Thank you so much! I was using VSCode and I had to change the End of Line Sequence from CRLF to LF. Thank you so much, really!
    – Zebiano
    Commented Feb 8, 2020 at 14:04
  • 2
    Without root you don't have too many choices to run a script from. If you want to run from adb shell, it can be either /sdcard or /data/local/tmp. If you want to run from a terminal emulator app, it can be either /sdcard or app's private directory in /data/data. There is no criteria to decide the best location. It depends on your specific requirements or comfort level. Commented Feb 8, 2020 at 16:20
  • 1
    Try termux from Play Store Commented Feb 9, 2020 at 6:31
  • @IrfanLatif Don't forget that you can't call a script directly (using ./myscript.sh) if it resides on a FAT32 file system, as it does not support file permissions. (SD cards are always formatted to FAT32) However, you can still use the format sh myscript.sh
    – Scooby-2
    Commented Feb 5 at 12:00

3 Answers 3

8

/storage/emulated/0 is usually mounted in a way that prevents execution of programs from this location.

Therefore even with a set executable bit for your script you won't be able to execute it directly. Of course you can still execute it via sh:

/system/bin/sh /storage/emulated/0/test.sh

Alternatively there is the directory /data/local/tmp which is writable without root (e.g. via adb). There you can place a script and execute it directly.

Note: Listing the content of /data and /data/local is denied for non-root users, but in /data/local/tmp you have permissions again.

6
  • Thank you for your answer! I've tried /data/local/tmp already, and unfortunately it didn't work. But I do see that its permissions are set to executable so the answer to my question might be just that! I've always executed my scripts with sh script.sh. If I'm understanding you correctly, you're saying running sh /storage/emulated/0/script.sh should work? Because that's what used to work, and suddenly stopped working.
    – Zebiano
    Commented Feb 8, 2020 at 13:04
  • @Zebiano /system/bin/sh /storage/emulated/0/script.sh definitely works on my Android 9 system (non-rooted). May be you accidentally installed a second sh executable that is now used instead of /system/bin/sh?
    – Robert
    Commented Feb 8, 2020 at 13:07
  • I just tried it on my system again and unfortunately had no luck. I doubt I installed a second one because I don't even know how to. I haven't installed anything on my phone besides BusyBox. Could switching between Mac and Windows with adb affect something?
    – Zebiano
    Commented Feb 8, 2020 at 13:14
  • @Zebiano No switching between Mac/Windows can not cause this effect. Adb is just a remote connector just like an ssh client.
    – Robert
    Commented Feb 8, 2020 at 13:20
  • Now that I've managed to get my scripts to run again, and after deciding that I want to execute my scripts (rather than sourcing them) by reading this, would you still recommend /data/local/tmp as a directory? Or should I pick another one?
    – Zebiano
    Commented Feb 8, 2020 at 14:18
1

I am using the Pydroid3 app over the same device configuration.

sh script.sh seems to work in it.

1

I am using a Samsung A52 (SM-A525F/DS) with Termux installed from Google Play. The home directory, where you can write scripts and set the execute bit, is:

/data/data /com.termux/files/home

You cannot browse this directory from a file manager on the phone, so a workaround is required to put your scripts there. I have created sub-directories from the home Termux directory, so it looks like this:

/data/data /com.termux/files/home/myname/scripts

This is the only place where you can execute scripts directly using:

./myscript.sh

although you can call bash in a new shell and feed its commands from a text file, which does not need to be executable, as in:

bash myscript.sh

The first line of the scripts must be

#!/data/data/com.termux/files/usr/bin/bash

Termux provides links to the standard directories DCIM, Download, Movies, Music, Pictures and one to the parent directory of all of the above, which is:

$HOME/storage/shared

However, from here, you can access all the standard directories with read and write permissions (as well as create your own, of course). Here is the output from the tree command run from the home directory on my phone, which explains it better than words:

$HOME
├── myname
│   └── scripts
└── storage
    ├── dcim -> /storage/emulated/0/DCIM
    ├── downloads -> /storage/emulated/0/Download
    ├── movies -> /storage/emulated/0/Movies
    ├── music -> /storage/emulated/0/Music
    ├── pictures -> /storage/emulated/0/Pictures
    └── shared -> /storage/emulated/0
        ├── Alarms
        ├── Android
        ├── Audiobooks
        ├── DCIM
        │   ├── Camera
        │   ├── Screenshots
        │   └── mei
        ├── Dashcam
        ├── Documents
        │   ├── Termux
        │   └── 2024-02-02_scripts
        ├── Download
        │   └── .scripts (Latest versions go here using get.sh/put.sh)
        ├── GIFs
        ├── Movies
        │   ├── Whatsapp
        │   └── Downloaded_Videos
        ├── Music
        │   └── Downloaded_MP3s
        ├── Notes
        ├── Notifications
        ├── Podcasts
        ├── Recordings
        └── Ringtones
27 directories

From my scripts directory I have written scripts called get.sh and put.sh to help move files between my PC and the phone, as it's easier to script on a PC's big screen. I use a hidden directory in the Download directory called ".scripts" as the point to access files on both my cable-connected PC and from Termux. All I have to do is make them executable once they are in the scripts directory.

In Documents, I transfer copies of the current scripts, the Termux setup files and my $HOME/.profile in directories called Termux and scripts. This is how I maintain back up files.

I hope this helps someone.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .