Solved How to call an external .sh file from within python in FreeBSD?

usdmatt

Daemon

Reaction score: 602
Messages: 1,543

Did you add those python commands to the plugin?
If so, try making a small python script to do the same thing and run it manually. If that doesn't work then there's something wrong with the python install itself. If it does, then it's something to do with the way the plugin runs python (such as the user account it uses)
 
OP
iSh0w

iSh0w

Member


Messages: 34

Did you add those python commands to the plugin?
If so, try making a small python script to do the same thing and run it manually. If that doesn't work then there's something wrong with the python install itself. If it does, then it's something to do with the way the plugin runs python (such as the user account it uses)

Yup, added those commands and ran. That sounds like something that would bring more clarity, will try the direct python install to check.

The way the plug-in runs python is the million dollar question ;) if you follow the posts in the thread, both wblock@ and tobik have been helping and felt the same way. On the other hand, it is possible to import io and write into the sh file, it is possible to change the working directory. So, felt that the sandbox kind of python the plug-in is running in is not really protecting/stopping the .sh file from being run. The OP shows for all other OS's what has successfully been used to call the .sh file, that's what's got me stumped, why just FreeBSD

/iSh0w
 
Last edited by a moderator:
OP
iSh0w

iSh0w

Member


Messages: 34

Ok, just to confirm, ran the below in terminal and it successfully wrote the timestamp into the run.log file based on the test.sh file
Similar to what wblock@ has checked here
Code:
Python 2.7.10 (default, Jul  5 2015, 01:15:55)
[GCC 4.2.1 Compatible FreeBSD Clang 3.4.1 (tags/RELEASE_34/dot1-final 208032)] on freebsd10
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.system('sh /root/Desktop/test.sh');
0
>>>

/iSh0w
 
Last edited by a moderator:
OP
iSh0w

iSh0w

Member


Messages: 34

Try putting the full path to sqlite3 in the script.
Most of the commands you've tried should work on FreeBSD so it must be something to do with the shell script. Creating a simple script as suggested by wblock@ is a good first step (for instance my test script below just outputs a line of text with echo).

Code:
import os
import subprocess

subprocess.call(["sh", "test.sh"])
subprocess.Popen(["sh", "test.sh"])
os.system('sh test.sh');
Code:
#!/bin/sh

echo "From shell script PID ${$}"
Code:
# python2.7 test.py
From shell script PID 74269
From shell script PID 74270
From shell script PID 74271
#


All the three methods suggested by you worked when directly when run in terminal

Code:
You have mail.
root@l0ck:~ # python
Python 2.7.10 (default, Jul  5 2015, 01:15:55)
[GCC 4.2.1 Compatible FreeBSD Clang 3.4.1 (tags/RELEASE_34/dot1-final 208032)] on freebsd10
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> subprocess.call(["sh", "/root/Desktop/test.sh"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'subprocess' is not defined
>>> import subprocess
>>> subprocess.call(["sh", "/root/Desktop/test.sh"])
0
>>> subprocess.Popen(["sh", "/root/Desktop/test.sh"])
<subprocess.Popen object at 0x80076afd0>
>>> subprocess.Popen(["sh", "/root/Desktop/test.sh"])
<subprocess.Popen object at 0x80076af90>
>>>

So I guess it is what wblock@ and you have been saying that there is a kind of a sandbox environment of sorts regarding the plex python based plug-in framework is correct :/ Although, it does a lot of other stuff, except this...wish there were a command line based solution as root to un-sandbox it or maybe use the systems python...

/iSh0w
 
Last edited by a moderator:
OP
iSh0w

iSh0w

Member


Messages: 34

Tried the following, no joy :/
Code:
subprocess.call(["sh", "-c", "/root/Desktop/L0ck.sh"])
subprocess.Popen(["sh", "-c", "/root/Desktop/L0ck.sh"])




Ok, so the code below did throw an error

Code:
retval = subprocess.check_call(["/root/Desktop/L0ck.sh"], shell=True)
retval.communicate()


2015-07-22 16:58:27,939 (80623f800) : CRITICAL (runtime:883) - Exception (most recent call last):
File "/usr/local/plexdata/Plex Media Server/Plug-ins/Framework.bundle/Contents/Resources/Versions/2/Python/Framework/components/runtime.py", line 843, in handle_request
result = f(**d)
File "/usr/local/plexdata/Plex Media Server/Plug-ins/L0ck.bundle/Contents/Code/__init__.py", line 91, in L0ck
retval = subprocess.check_call(["/root/Desktop/L0ck.sh"], shell=True)
File "/usr/local/share/plexmediaserver/Resources/Python/lib/python2.7/subprocess.py", line 542, in check_call
raise CalledProcessError(retcode, cmd)
CalledProcessError: Command '['/root/Desktop/L0ck.sh']' returned non-zero exit status 127



Hey newbie32,
Based on the result "non-zero exit status 127" Googled and found this which states:

Value 127 is returned by /bin/sh when the given command is not found within your PATH system variable and it is not a built-in shell command. In other words, the system doesn't understand your command, because it doesn't know where to find the binary you're trying to call.

Would that suggest I need to change the hash-bang?

/iSh0w

Ps:- This is most revealing and exciting as now we can see in what exact way the Plex python plug-in framework is sandboxed and maybe find a workaround as root!?
 
Last edited by a moderator:

usdmatt

Daemon

Reaction score: 602
Messages: 1,543

Did you ever update the script to use the full path to sqlite3?
Just because sqlite3 is in your PATH when on the console doesn't mean it will be when Plex runs its plugins.

Another obvious thing to check is what user the plugins are run as, and whether that user has file system permission to access the script (including read/execute on the parent directories), and access to write to the database file.
 
OP
iSh0w

iSh0w

Member


Messages: 34

Did you ever update the script to use the full path to sqlite3?
Just because sqlite3 is in your PATH when on the console doesn't mean it will be when Plex runs its plug-ins.

Another obvious thing to check is what user the plug-ins are run as, and whether that user has file system permission to access the script (including read/execute on the parent directories), and access to write to the database file.

Not really, will do ASAP, was trying the test script and figured that would run. Will use the entire path/to/sqlite3 and revert

Yes, double checked permissions, plex : plex . All the plug-ins have the same rights drwxr-xr-x
Ran
chown -R plex:plex L0ck.bundle
chmod 755 L0ck.bundle

For the .sh file
Ran
chmod 755 L0ck.sh


/iSh0w
 
Last edited by a moderator:
OP
iSh0w

iSh0w

Member


Messages: 34

Did you ever update the script to use the full path to sqlite3?
Just because sqlite3 is in your PATH when on the console doesn't mean it will be when Plex runs its plugins.

Another obvious thing to check is what user the plugins are run as, and whether that user has file system permission to access the script (including read/execute on the parent directories), and access to write to the database file.

Just updated the L0ck.sh with the path to sqlite3, runs when manually clicked, does not get called via python

Code:
#!/bin/sh

/usr/local/bin/sqlite3 "/usr/local/plexdata/Plex Media Server/Plug-in Support/Databases/com.plexapp.plugins.library.db" "UPDATE metadata_items SET metadata_type=20 WHERE library_section_id=2 and metadata_type=1; DELETE FROM library_sections WHERE id=2;"

exit;
 
OP
iSh0w

iSh0w

Member


Messages: 34

:D can you guess why I have this grin :D

One or more of these worked after changing the sqlite3 path :))

IT WORKED!!! Thanks a ton you guys!

Code:
    os.popen(filepath)
    os.system('sh ' + '\"/usr/local/plexdata/Plex Media Server/Plug-ins/L0ck.bundle/Contents/Resources/l0ck_support/l0ck.sh\"')
    os.system(filepath)   
    os.system("open " + filepath)
    os.system("xdg-open" + filepath)   
    os.system("sh " + filepath)   
    os.system("/bin/sh " + filepath)
    os.system("/ " + filepath)
    os.system("/bin/sh"  + filepath)
    subprocess.call(["ls" , "-l"])
    subprocess.call(["sh", "-c", filepath])
    subprocess.Popen(["sh", "-c", filepath])
    #retval = subprocess.check_call([filepath], shell=True)
    #retval.communicate()
    subprocess.Popen(["sh", filepath])
    os.system('sh filepath');
    subprocess.Popen(["/bin/sh" , filepath])
    subprocess.Popen(filepath, shell=True, executable='/bin/sh')
    subprocess.Popen(["sh", filepath]).wait()   
    subprocess.Popen([filepath], shell=True)
    process = subprocess.Popen(['/bin/sh','-c',filepath], stdout=subprocess.PIPE)
    process.communicate()

Probably more than one of these will work as of now, this
Code:
os.popen(filepath)
just worked fine so sticking to it!

Why it wasn't working earlier is was trying to run L0ck.sh from the desktop so as to use a straightforward path, however, then the L0ck.sh was not part of the L0ck.bundle and was probably not getting the correct rights!

Thanks to all, especially usdmatt, respect!
 
OP
iSh0w

iSh0w

Member


Messages: 34

:D :D :D
Just a query, is there a standalone sqlite3 that I can pack with the .sh files so as to avoid compatibility issues.
I do that for Linux, Mac and Windows, however could not find a sqlite3 for FreeBSD.

Thanks again!

/iSh0w
:D :D :D
 
Top