Permission Denied when trying to run Shell Script (containing Python sub-script) - python

I'm currently creating a Raspberry Pi (Model B) based temperature sensor with a display. I am trying to run a shell start up script in the LX Terminal but keep getting a "Permission Denied" error next to a Python sub-script as follows:
pi#raspberrypi ~ $ sudo /home/pi/tempsense/etc/init.d/envmon start
Starting envmon
pi#raspberrypi ~ $ /home/pi/tempsense/etc/init.d/envmon: 15:/home/pi/tempsense/etc/init.d/envmon: home/pi/tempsense/opt/envmon/displayenvmon.py: Permission denied
The shell script is:
#!/bin/sh
### BEGIN INIT INFO
# Provides: envmon
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop envmon
### END INIT INFO
case "$1" in
start)
/home/pi/tempsense/opt/envmon/dht11 &
echo "Starting envmon"
/home/pi/tempsense/opt/envmon/displayenvmon.py &
;;
stop)
pkill dht11
pkill displayenvmon
echo "envmon stopped"
;;
*)
echo "Usage: /home/pi/tempsense/etc/init.d/envmon {start|stop}"
exit 1
;;
esac
exit 0
The Python script causing the Permission denied errors is:
#!/usr/local/lib/python2.7/dist-packages
from RPLCD import CharLCD
import RPi.GPIO as GPIO
import subprocess, re
import time
# Data file - current reading
datfile = "/var/envmon.data"
# Rate at which the LCD is updated
UPDATE_RATE = 5
lcd = CharLCD(cols=16, rows=2,
pin_rw=None,
pin_rs=7,
pin_e=8,
pins_data=[25,24,23,18],
numbering_mode=GPIO.BCM)
lcd.cursor_pos = (0, 0)
lcd.write_string('Visit #UWS_Pi')
lcd.cursor_pos = (1, 0)
lcd.write_string('TEMP & HUMID')
time.sleep(5);
# Get IP address - looks for first IP address which is not 127.0.0.1
address_string = subprocess.getoutput("ip addr")
ipaddr = "Unknown"
# Reg exp to extract IP addresss
search_inet = re.compile('inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
for line in address_string.split('\n') :
match = search_inet.search(line)
if (match != None) :
if (match.group(1) != '127.0.0.1') :
ipaddr = match.group(1)
break
# Print the IP address to the LCD
lcd.cursor_pos = (1,0)
lcd.write_string (ipaddr)
# Sleep to give chance to read IP address
time.sleep(5)
# Loop get most recent reading and display on screen
while (True):
fh = open (datfile, "r")
entry = fh.read()
# split into separate entries
[currtime, currtemp, currhumid] = entry.split()
# Change currtime to a formatted time ready for displaying
formattime = time.strftime ("%d/%m/%Y %H:%M", time.localtime(int(currtime)))
# print time to display
lcd.cursor_pos = (0,0)
lcd.write_string (formattime)
# Print temp and humidity values
lcd.cursor_pos = (1,0)
lcd.write_string ("T " + currtemp + "C RH " + currhumid + "% ")
time.sleep(UPDATE_RATE)
I am new to this and any helpful advice is appreciated.

To use the GPIO pins, the Python script needs to be run with administrator privileges. Either execute the shell script as root or call your Python script using sudo from within the shell script.

Either log in as root, or run the program with sudo, because usually permission denied means you need root permissions, sudo runs that specific program with root permissions if you don't want to log in as root.

Related

trying to replace netcat ,, with a python script

I'm reading a book called ( Black Hat Python: Python Programming for Hackers and Pentesters
Book by Justin Seitz)
and I'm doing a project from the book called Replacing Netcat , basically an attempt to replace netcat with a python script ,
I wrote the code identical to the book but its not running properly,,,
** I mean I had to make some obvious changes , cause the book is using python 2.7 , and I'm using Python 3.9.12**
but the code isn't working as it should , according to the book,,,,
this is how the book is telling me to run the code ::- how the book tells me to run the script
me trying to run the code 1st step
me trying to run the code 2nd step
as u can see it gives no output ,, if I try to run it according to the book
and just print's the strings and stops when I write "python3 file_name.py" 2
and stops , it doesn't even execute a single function after that, what am I doing wrong ?
import sys
import socket
import getopt
import threading
import subprocess
# global variables that we fooking need .
listen = False
command = False
upload = False
execute = ""
target = ""
upload_dest = ""
port = 0
def usage():
print ("BHP Net Tool")
print()
print ("Usage: bhpnet.py -t target_host -p port")
print ("""-l --listen - listen on [host]:[port] for ¬
incoming connections""")
print ("""-e --execute=file_to_run - execute the given file upon ¬
receiving a connection""")
print ("-c --command - initialize a command shell")
print ("""-u --upload=destination - upon receiving connection upload a ¬
file and write to [destination]""")
print()
print()
print ("Examples: ")
print ("bhpnet.py -t 192.168.0.1 -p 5555 -l -c")
print ("bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe")
print ("bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\"")
print ("echo 'ABCDEFGHI' | ./bhpnet.py -t 192.168.11.12 -p 135")
sys.exit(0)
def main():
global listen
global port
global execute
global command
global upload_dest
global target
if not len(sys.argv[1:]):
usage()
# read commandline options
try:
opts,args = getopt.getopt(sys.argv[1:],"hle:t:p:cu:",
["help", "listen", "execute", "target", "port", "command", "upload"])
except getopt.GetoptError as err:
print(str(err))
usage()
for o,a in opts:
if o in ("-h", "--help"):
usage()
elif o in ("-l", "--listen"):
listen = True
elif o in ("-e", "--execute"):
execute = a
elif o in ("-c", "commandshell"):
command = True
elif o in ("-u", "--upload"):
upload_dest = a
elif o in ("-t", "--target"):
target = a
elif o in ("-p", "--port"):
port = int(a)
else:
assert False, "Unhandled Option"
#are we going to listen or just send data from stdin ?
if not listen and len(target) and port > 0 :
#read in buffer from the commandline
#this will block , so send CTRL-D if not sending input
#to stdin
buffer = sys.stdin.read()
# send data off
client_sender(buffer)
# we are going to listen and potentially
# upload things , execute commands , and drop a shell back
# depending on our command line options above
if listen:
server_loop()
main()
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# connect to out target host
client.connect((target,port))
if len(buffer):
client.send(buffer)
while True:
# now wait for back
recv_len = 1
response = ""
while recv_len:
data = client.recv(4096)
recv_len = len(data)
response += data
if recv_len < 4096:
break
print(response)
# wait for more input
buffer = input("")
buffer += "\n"
# send it off
client.send(buffer)
except:
print("[*] Exception ! Exiting.")
# tear down the connection
client.close()
def server_loop():
global target
#if no target is defined, we listen on al interfaces
if not len(target):
target = "0.0.0.0"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target,port))
server.listen(5)
while True:
client_socket, addr = server.accept()
# spin off a thread to handel our new client
client_thread = threading.Thread(target=client_handler, args = (client_socket,))
client_thread.start()
def run_command(command):
# trim the newline
command = command.rstrip()
# run the command and get the output back
try:
output = subprocess.check_output(command,stderr = subprocess.STDOUT, shell=True)
except:
output = "Failed to execute command.\r\n"
#send the output back to the client
return output
def client_handler(client_socket):
global upload
global exceute
global command
# check for upload
if len(upload_dest):
# read in all of the bytes and write to our destination
file_buffer = ""
#keep reading data until none is available
while True:
data = client_socket.recv(1024)
if not data:
break
else:
file_buffer += data
# now we take these bytes and try to write them out
try:
file_descriptor = open("upload_dest", "wb")
file_descriptor.write(file_buffer)
file_descriptor.close()
# acknowledge that we wrote the file out
client_socket.send(f"Succesfully saved file to {upload_dest}")
except:
client_socket.send(f"Failed to save file to \r\n{upload_dest}")
# check for command execution
if len(execute):
# run the command
output = run_command(execute)
client_socket.send(output)
# now we go into another loop if a command shell was requested
if command:
while True:
# show a simple prompt
client_socket.send("<BHP:#>")
# now we recive until we see a linefeed ( enter key )
cmd_buffer = ""
while "\n" not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
# send back the command output
response = run_command(cmd_buffer)
# send back the response
client_socket.send(response)
How is your debugging skill?
I was experiencing the same issue afew days ago & i fixed it by debugging entry points into functions to keep track of the eip while the program is running by printing arguments before any operation as they are being passed between functions .. this helps to check whether the code is producing expected values as it runs ..
in short as this case , the book was written in regards to python2 so most of the errors are going to force you to work on your debugging skills..
i would also advice you to take a short crash course in C programming before taking on the BHP book since alot of system calls like socket getopts are really C apis , check on man 2 and man 3 of whatever you're importing in python to have a broader look on things as you debug most errors ..
managed to fix it up until here ..
download source code link
https://filebin.net/i40e2oisabxqmbys

My daemon die directly after starting

I have to develop a program with Python3 which executes automatically programs at specific times. I must use a daemon and I can't use external libraries.
That's why I create an install program which configure the daemon (I followed this tutorial https://openclassrooms.com/courses/faire-un-demon-sous-linux).
The file gobatch is the program which executes automatically programs.
#! /usr/bin/python3
# -*- coding: utf8 -*-
import os
import sys
import time
import shutil
# Check if script is start with root rights
if os.geteuid() != 0:
exit('You need to have root privileges to run this script. Use \'sudo ./install.py\'.')
# Title
print('----- ProcessManager install ----- \n')
time.sleep(1)
# Get path of gobatch file
gobatchPath = input("Please enter the path (absolute) where the ProcessManager gobatch program is located: ")
# Check if file exists
try:
with open(gobatchPath):
pass
except IOError:
exit('Error : file does not exists.')
# Copy gobatch file into /usr/bin/
shutil.copy(gobatchPath, '/usr/bin/gobatch')
# Create and fill the automatic launch program
description = 'Deamon that allows you to run cyclicaly at a date or a specific time a program'
fileContent = '#### BEGIN INIT INFO \n' \
'# Provides: chillispot et freeradius dans le chroot \n' \
'# Required-Start: $local_fs $network \n' \
'# Required-Stop: $local_fs $remote_fs _\n' \
'# Default-Start: 2 3 4 5 \n' \
'# Default-Stop: 0 1 6 \n' \
'# Short-Description: Wireless & LAN Access Point Controller \n' \
'# Description: ChilliSpot is an open source captive portal \n' \
'# or wireless LAN access point controller. \n' \
'### END INIT INFO \n\n\n' \
'DESC="' + description + '"\n' \
'DEAMON=/usr/bin/gobatch'
file = open('/etc/init.d/gobatch', 'w')
file.write(fileContent)
file.close()
# Give the rights
os.chmod('/etc/init.d/gobatch', 0o755)
# Save gobatch file to be active
os.system('update-rc.d gobatch defaults')
However, when I start the service with : /etc/init.d/gobatch start and displaying the status with service gobatch status I get
gobatch.service - SYSV: ChilliSpot is an open source captive portal
Loaded: loaded (/etc/init.d/gobatch; bad; vendor preset: enabled)
Active: inactive (dead)
Docs: man:systemd-sysv-generator(8)
Can you tell me if my way is the right method or it exists other solutions?
And do you have any idea why my daemon die directly after starting?
Thank's for help!
UPDATE
Currently, my gobatch file is not a real program because I prefer create the deamon before.
gobatch file
#! /bin/bash
echo "it works !"
My work is to create the installer of the daemon, not the gobatch program. It's another person who must do that. That's why I'm using a minmial content.
UPDATE 2:
My new /etc/init.d/gobatch :
#!/bin/sh
#### BEGIN INIT INFO
# Provides: chillispot et freeradius dans le chroot
# Required-Start: $local_fs $network
# Required-Stop: $local_fs $remote_fs _
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Wireless & LAN Access Point Controller
# Description: ChilliSpot is an open source captive portal
# or wireless LAN access point controller.
### END INIT INFO
PATH=/bin:/usr/bin:/sbin:/usr/sbin
DESC="Deamon that allows you to run cyclicaly at a date or a specific time a program"
NAME=gobatch
DEAMON=/usr/sbin/gobatch
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/"$NAME"
. /lib/lsb/init-functions
case "$1" in
start) log_daemon_msg "Starting gobatch"
start_daemon -p $PIDFILE $DAEMON
log_end_msg $?
;;
stop) log_daemon_msg "Stopping gobatch"
killproc -p $PIDFILE $DAEMON
RETVAL=$?
[ $RETVAL -eq 0 ] && [ -e "$PIDFILE" ] && rm -f $PIDFILE
log_end_msg $RETVAL
;;
restart) log_daemon_msg "Restarting gobatch"
$0 stop
$0 start
;;
esac
exit 0
With this code I get this error :
gobatch.service: Failed at step EXEC spawning /etc/init.d/gobatch: Exec format error
UPDATE 3:
The last error into logs file is :
janv. 08 15:33:07 ubuntu systemd[1]: Failed to start SYSV: ChilliSpot is an open source captive portal.
I hope after that, my program will works.
Your script echoes and exits immediately, so it is not a deamon. A daemon needs to continue running after invocation.
You need to have a program that behaves like a deamon in order to test its installation. The installation will not create a deamon out of a regular program. It will only prepare the environment for running it.
The question How do you create a daemon in Python? will give you more information how to write a proper daemon in Python.
I suspect that once your gobatch prints the executions is done.
Try
#! /bin/bash
for i in $(seq 1 10)
do
echo "it works !"
sleep 1
done

Called bashscript doesn't start up GNU screen session

I have a problem with a backup script which is supposed to call a bash starting/stopping script, in which a "daemon" (via GNU screen) is managed. For the moment my python backup script is called via cron. Within the launch.sh script there is a determination of the given parameter. If "stop" is given the script echos "Stopping..." and runs the GNU screen command to shut down the session. The same goes for "start". If the script is called via subprocess.call(...,Shell=True) in Python the string is shown but the screen session remains untouched. If it gets called directly in bash everything works fine.
#!/usr/bin/env python
'''
Created on 27.07.2013
BackUp Script v0.2
#author: Nerade
'''
import time
import os
from datetime import date
from subprocess import check_output
import subprocess
script_dir = '/home/minecraft/automated_backup'
#folders = ['/home/minecraft/staff']
folders = ['/home/minecraft/bspack2','/home/minecraft/staff']
# log = 0
backup_date = date.today()
backup_dir = '/home/minecraft/automated_backup/' + backup_date.isoformat()
def main():
global log
init_log()
init_dirs()
for folder in folders:
token = folder.split("/")
stopCmd = folder + '/launch.sh stop'
log.write("Stopping server %s...\n" % (token[3]))
subprocess.call(stopCmd,shell=True)
#print stopCmd
while screen_present(token[3]):
time.sleep(0.5)
log.write("Server %s successfully stopped!\n" % (token[3]))
specificPath = backup_dir + '/' + token[3]
os.makedirs(specificPath)
os.system("cp /home/minecraft/%s/server.log %s/server.log" % (token[3],specificPath))
backup(folder,specificPath + '/' + backup_date.isoformat() + '.tar.gz')
dumpDatabase(backup_dir)
for folder in folders:
token = folder.split("/")
startCmd = folder + '/launch.sh start'
log.write("Starting server %s...\n" % (token[3]))
subprocess.call(startCmd,shell=True)
time.sleep(1)
log.write(screen_present(token[3]))
#print startCmd
def dumpDatabase(target):
global log
log.write("Dumping Database...\n")
cmd = "mysqldump -uroot -p<password> -A --quick --result-file=%s/%s.sql" % (backup_dir,backup_date.isoformat())
os.system(cmd)
#print cmd
def backup(source,target):
global log
log.write("Starting backup of folder %s to %s\n" % (source,target))
cmd = 'tar cfvz %s --exclude-from=%s/backup.conf %s' % (target,source,source)
os.system(cmd)
#print cmd
def screen_present(name):
var = check_output(["screen -ls; true"],shell=True)
if "."+name+"\t(" in var:
return True
else:
return False
def init_log():
global log
log = open("%s/backup.log" % script_dir,'a')
log.write(
"Starting script at %s\n" % time.strftime("%m/%d/%Y %H:%M:%S")
)
def init_dirs():
global backup_dir,log
log.write("Checking and creating directories...\n")
if not os.path.isdir(backup_dir):
os.makedirs(backup_dir)
if __name__ == '__main__':
main()
And the launch.sh:
#!/bin/sh
if [ $# -eq 0 ] || [ "$1" = "start" ]; then
echo "Starting Server bspack2"
screen -S bspack2 -m -d java -Xmx5G -Xms4G -jar mcpc-plus-legacy-1.4.7-R1.1.jar nogui
fi
if [ "$1" = "stop" ]; then
screen -S bspack2 -X stuff 'stop\015'
echo "Stopping Server bspack2"
fi
What's my problem here?
I'm sure by now you've solved this problem, but looking through your question I'd bet the answer is remarkably simple -- mcpc-plus-legacy-1.4.7-R1.1.jar isn't found by java, which fails, and subsequently screen terminates.
In launch.sh, screen will execute in the same directory as the calling script. In this case, your python script, when run by cron, will have an active directory of the running user's home directory (so root crontabs will run in /root/, for instance, and a user crontab in /home/username/).
Simple solution is just to the following:
cd /home/minecraft/bspack2
as the second line in your launch.sh script, just after #!/bash/sh.
In the future, I'd recommend when interacting with screen to leverage the -L parameter. This turns on autologging. By default, in the current directory a file "screenlog.0" will be generated when screen terminates, showing you a log history of activity during the screen session. This will allow you to debug screen problems with ease, and help encourage keeping track of "current directory" while working with shell scripts, to make finding the screen log output simple.

Script execution stops at os.execlpe()

I am a bit of a newbie on Python, but was was testing some things I learned on Ubuntu.
Basically, this script is supposed to set your TCP/IP config, then restart the networking daemon and display the changes.
This is the whole script:
#!/usr/bin/env python
import commands
import os
import sys
euid = os.geteuid()
if euid != 0:
print "Script not started as root. Running sudo.."
args = ['sudo', sys.executable] + sys.argv + [os.environ]
# the next line replaces the currently-running process with the sudo
os.execlpe('sudo', *args)
print 'Running. Your euid is', euid
print "IP"
IP = raw_input(">>")
print "Gateway"
PE = raw_input(">>")
ifconfig = commands.getoutput("ifconfig")
interfaz = ifconfig[0:5]
ArchivoInterfaces = open("/etc/network/interfaces", "w")
ArchivoInterfaces.write("#auto lo\n#iface lo inet loopback\nauto %s\niface %sinet static\naddress %s\ngateway %s\nnetmask 255.255.255.0"%(interfaz, interfaz, IP, PE))
ArchivoInterfaces.close()
ArchivoResolv = open("/etc/resolv.conf", "w")
ArchivoResolv.write("# Generated by NetworkManager\ndomain localdomain\nsearch localdomain\nnameserver 8.8.8.8\nnameserver 8.8.4.4")
ArchivoResolv.close()
os.execlpe('/etc/init.d/networking', "test","restart", os.environ)
print "Todo esta correcto, su IP ahora es %s" %(IP)
fin = raw_input("write d and press enter to show the changes, or press enter to exit.")
if fin == "d":
ArchivoResolv = open("/etc/resolv.conf")
ArchivoInterfaces = open("/etc/network/interfaces")
ifconfig2 = commands.getoutput("ifconfig")
print "ARCHIVO resolv.conf\n"+ArchivoResolv.read()+"\n\n"+"ARCHIVO interfaces\n"+ArchivoInterfaces.read()+"\n\n"+"RESULTADO DE \"ifconfig\"\n"+ifconfig2
fin = raw_input("Presiona ENTER para salir.")
Unfortunately, it keeps stopping on this line - and I'm not sure why:
os.execlpe('/etc/init.d/networking', "test","restart", os.environ)
After reaching this spot, the script runs the restart, and then just exits.
I would love to get it to run the last part of the script so I can see what changed, but I'm unable. Any ideas?
Because all of the exec family of functions work by replacing the current process with the one you execute.
If you just want to run an external command, use the spawn functions instead. (In this case, os.spawnlpe is very nearly a drop-in replacement.)
os.execlpe (and the similar os.exec* functions) replace the current process:
These functions all execute a new program, replacing the current process; they do not return.

Python SimpleXMLRPC fails when starting from Crontab but not in local shell

I am really puzzled on this issue. I am using python's SimpleXMLRPC to provide services to a web application.
The problem is that when I start my xmlrpc server from the command line everything runs smoothly but when it is started through crontab it doesn't.
I have tried to hold the start-up via sleep and checking /sys/class/net/eth0/device/net/eth0/operstate but got no luck.
Please find attached the source for the script:
#!/usr/local/bin/python2.5
# -*- coding: utf-8 -*-
# License: GNU
# startxmlrpc.py: startup script for xmlrpc server to deal with processing
## {{{ http://code.activestate.com/recipes/439094/ (r1)
import socket
import fcntl
import struct
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
## end of http://code.activestate.com/recipes/439094/ }}}
import xmlrpclib
import urllib2
import os
from SimpleXMLRPCServer import SimpleXMLRPCServer
from time import sleep
def send(img1,img2,lib,filters):
global HOST_IP
path = '/var/www/%s/' % MD5Cypher(HOST_IP)
makedirs(path)
print "Path: %s" % path
if lib=='devel':
os.system("""python ~/devel_funcs.py %s %s "%s" &""" % (img1_path,img2_path, filters))
if lib=='milena':
import milena_funcs
milena_funcs.mln_process(img1_path, filters)
return HOST_IP + '/' + path.split('/var/www/')[1] + 'out.pgm'
while open('/sys/class/net/eth0/operstate').read().strip() != 'up':
sleep(5)
HOST_IP = get_ip_address('eth0')
server = SimpleXMLRPCServer((HOST_IP, 7070))
server.register_function(send)
server.serve_forever()
This is the error I get if I try to launch my process just after a clean boot:
<class 'xmlrpclib.Fault'>: <Fault 1: "<class 'xmlrpclib.ProtocolError'>:<ProtocolError for 192.168.0.5:7070/RPC2: -1 >">
args = ()
faultCode = 1
faultString = "<class 'xmlrpclib.ProtocolError'>:<ProtocolError for 192.168.0.5:7070/RPC2: -1 >"
message = ''
If I kill it and run it again, it works.
This is the crontab:
usrmln#Slave1:~$ crontab -l
# m h dom mon dow command
* * * * * python ~/master_register.py > /dev/null 2>&1
* * * * * python ~/startxmlrpc.py > /dev/null 2>&1
0 5 * * * find /var/www/ -type d -mtime +3 -exec rm -rf {} \; > /dev/null 2>&1
You don't show what the error is, but, it is possibly that PYTHONPATH is not being set when run from cron. You could set it before running the script.
Or, of course, you are running it as a different user and file permissions are not correctly set. Also ~/devel_funcs.py will not refer to your home directory if cron runs your script as a different user.
I finally got it, I was using python 2.5 locally and I had to add to the execution like this:
/usr/local/bin/python2.5 /home/username/startxmlrpc.py > /dev/null 2>&1

Categories