15

I have the most simple script called update.sh

#!/bin/sh
cd /home/pi/circulation_of_circuits
git pull

When I call this from the terminal with ./update.sh I get a Already up-to-date or it updates the files like expected.

I also have a python script, inside that scipt is:

subprocess.call(['./update.sh'])

When that calls the same script I get:

Permission denied (publickey). fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

(I use SSH).

----------------- update --------------------

Someone else had a look for me:

OK so some progress. When I boot your image I can't run git pull in your repo directory and the bash script also fails. It seems to be because the bitbucket repository is private and needs authentication for pull (the one I was using was public so that's why I had no issues). Presumably git remembers this after you type it in the first time, bash somehow tricks git into thinking it's you typing the command subsequently but running it from python isn't the same.

I'm not a git expert but there must be some way of setting this up so python can provide the authentication.

sdikby
  • 1,383
  • 14
  • 30
clankill3r
  • 9,146
  • 20
  • 70
  • 126
  • Does this solve your issue (passing the `shell=true` flag): http://stackoverflow.com/a/325474/608259 – kalaracey Mar 05 '17 at 23:06
  • No, in case it matters I called it like this `cmd = ['/home/pi/circulation_of_circuits/update.sh'] process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) process.wait()` – clankill3r Mar 05 '17 at 23:21
  • In case someone wonders, `os.geteuid()` gives a 0 so that should be good. – clankill3r Mar 05 '17 at 23:29
  • If it returns 0 it thinks it is running as root. Are you running the Python script as root? If so then my original answer would apply. – kalaracey Mar 05 '17 at 23:31
  • 1
    `Permission denied (publickey). ` show that there are some problems with your ssh config, run python script with different user? – zzn Mar 06 '17 at 02:13
  • @kalaracey I'm running both scripts as root. And the shell=True didn't help. – clankill3r Mar 06 '17 at 08:27
  • @zzn How can I run the python script with a different user? – clankill3r Mar 06 '17 at 08:28
  • @clankill3r Who cloned the repository? `root` or someone else? – kennytm Mar 08 '17 at 09:13
  • Do you execute the script with sudo? – Tzomas Mar 08 '17 at 09:18
  • Try to execute the python script with -E option – Tzomas Mar 08 '17 at 09:36
  • I tried that as well, for example `subprocess.call(['sudo', './update.sh'])` but that does not change anything. – clankill3r Mar 08 '17 at 09:41
  • @Tzomas '-E' Also doesn't help. `sudo python -E c_of_c.py` – clankill3r Mar 08 '17 at 09:44
  • @kennytm `pi` is owner. – clankill3r Mar 08 '17 at 09:47
  • @clankill3r Will running that update.sh as `pi` cause any problem? Also, why the Python script needs to be run as `root` instead of `pi`? – kennytm Mar 08 '17 at 09:50
  • @kennytm I did `sudo chmod u+s c_of_c.py` And then run the script with `sudo python c_of_c.py` but that did not help. – clankill3r Mar 08 '17 at 11:10
  • @clankill3r No it's not about `sudo`. In fact you should not run as `root` for `git pull`. The question is, is there any reason you *must* run the script as `root`. – kennytm Mar 08 '17 at 11:24
  • 1
    Maybe you could try something like `cmd=['sudo', '-u', 'yourusername', 'path to your bash', '/home/pi/circulation_of_circuits/update.sh']` and see if that helps? This will run the script with your own user rights instead of sudo's, as kennytm's comment stated that you should **not** run as root to perform a git pull. – Montmons Mar 09 '17 at 16:50
  • Can you accept an answer @clankill3r? – jimh Apr 05 '17 at 17:44

9 Answers9

11

sounds like you need to give your ssh command a public or private key it can access perhaps:

ssh -i /backup/home/user/.ssh/id_dsa user@unixserver1.nixcraft.com

-i tells it where to look for the key

jimh
  • 1,651
  • 2
  • 15
  • 28
6

This problem is caused by the git repo authentication failing. You say you are using SSH, and git is complaining about publickey auth failing. Normally you can use git commands on a private repo without inputting a password. All this would imply that git is using ssh, but in the latter case it cannot find the correct private key.

Since the problem only manifests itself when run through another script, it is very likely caused by something messing with the environment variables. Subprocess.call should pass the environment as is, so there are a couple of usual suspects:

  1. sudo.
    • if you are using sudo, it will pass a mostly empty environment to the process
  2. the python script itself
    • if the python script changes its env, those changes will get propagated to the subprocess too.
  3. sh -lor su -
    • these commands set up a login shell, which means their environment gets reset to defaults.

Any of these reasons could hide the environment variables ssh-agent (or some other key management tool) might need to work.

Steps to diagnose and fix:

  1. Isolate the problem.

    • Create a minimal python script that does nothing else than runs subprocess.call(['./update.sh']). Run both update.sh and the new script.
  2. Diagnose the problem and fix accordingly:

    a) If update.sh works, and the new script doesn't, you are probably experiencing some weird corner case of system misconfiguration. Try upgrading your system and python; if the problem persists, it probably requires additional debugging on the affected system itself.

    b) If both update.sh and the new script work, then the problem lies within the outer python script calling the shell script. Look for occurrences of sudo, su -, sh -l, env and os.environ, one of those is the most likely culprit.

    c) If neither the update.sh nor the new script work, your problem is likely to be with ssh client configuration; a typical cause would be that you are using a non-default identity, did not configure it in ~/.ssh/config but used ssh-add instead, and after that, ssh-agent's cache expired. In this case, run ssh-add identityfile for the identity you used to authenticate to that git repo, and try again.

Bass
  • 206
  • 1
  • 8
3

I believe this answer will help you: https://serverfault.com/questions/497217/automate-git-pull-stuck-with-keychain?answertab=votes#tab-top

I didn't use ssh-agent and it worked: Change your script to the one that follows and try.

#!/bin/bash
cd /home/pi/circulation_of_circuits 
ssh-add /home/yourHomefolderName/.ssh/id_rsa
ssh-add -l
git pull

This assumes that you have configured correctly your ssh key.

Community
  • 1
  • 1
John Moutafis
  • 22,254
  • 11
  • 68
  • 112
3

It seems like your version control system, need the authentication for the pull so can build the python with use of pexpect,

import pexpect
child = pexpect.spawn('./update.sh')
child.expect('Password:')
child.sendline('SuperSecretPassword')
Rahul K P
  • 15,740
  • 4
  • 35
  • 52
2

Try using the sh package instead of using the subprocess call. https://pypi.python.org/pypi/sh I tried this snippet and it worked for me.

#!/usr/local/bin/python

import sh

sh.cd("/Users/siyer/workspace/scripts")
print sh.git("pull")

Output:

Already up-to-date.

Sridhar Iyer
  • 189
  • 1
  • 7
2
import subprocess 

subprocess.call("sh update.sh", shell=True)
Morgoth
  • 4,935
  • 8
  • 40
  • 66
  • 1
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – Donald Duck Mar 14 '17 at 10:02
  • i have added "sh update.sh" , because we can execute the shell script in two ways i.e 1) ./update.sh and 2) sh update.sh , here the both should work. but for him the 1 one is worked, so i was suggested him to try 2 one. thanks – Kanagaraj Dhanapal Mar 14 '17 at 10:54
  • You can [edit] your answer to to include more information. – Donald Duck Mar 14 '17 at 10:55
1

I can reproduce your fault. It has nothing to do with permission, it depends how your ssh are installed on your system. To verify it's the same cause i need the diff output.

Save the following to a file log_shell_env.sh,

#!/bin/bash

log="shell_env"$1
echo "create shell_env"$1

echo "shell_env" > $log

echo "whoami="$(whoami) >> $log
echo "which git="$(which git) >> $log
echo "git status="$(git status 2>&1) >> $log
echo "git pull="$(git pull 2>&1) >> $log
echo "ssh -vT git@github.com="$(ssh -T git@github.com 2>&1) >> $log

echo "ssh -V="$(ssh -V 2>&1) >> $log
echo "ls -al ~/.ssh="$(ls -a ~/.ssh) >> $log

echo "which ssh-askpass="$(which ssh-askpass) >> $log
echo "ps -e | grep [s]sh-agent="$(ps -e | grep [s]sh-agent ) >> $log
echo "ssh-add -l="$(ssh-add -l) >> $log

echo "set=" >> $log
set  >> $log

set execute permission and run it twice:
1. From the console without parameter
2. From your python script with parameter '.python'
Please, run it realy from the same python script!

   For instance:
    try:
        output= subprocess.check_output(['./log_shell_env.sh', '.python'], stderr=subprocess.STDOUT)
        print(output.decode('utf-8'))

    except subprocess.CalledProcessError as cpe:
        print('[ERROR] check_output: %s' % cpe)

Do a diff shell_env shell_env.python > shell_env.diff The resulting shell_env.diff should show not more than the following diffs:

15,16c15,16  
< BASH_ARGC=()
< BASH_ARGV=()
---
> BASH_ARGC=([0]="1")
> BASH_ARGV=([0]=".python")
48c48
< PPID=2209
---
> PPID=2220
72c72
< log=shell_env
---
> log=shell_env.python

Come back and comment, if you get more diffs update your Question with the diff output.

stovfl
  • 14,998
  • 7
  • 24
  • 51
1

With Git 1.7.9 or later, you can just use one of the following credential helpers:

With a timeout

git config --global credential.helper cache

... which tells Git to keep your password cached in memory for (by default) 15 minutes. You can set a longer timeout with:

git config --global credential.helper "cache --timeout=3600"

(That example was suggested in the GitHub help page for Linux.) You can also store your credentials permanently if so desired.

Saving indefinitely

You can use the git-credential-store via

git config credential.helper store

GitHub's help also suggests that if you're on Mac OS X and used Homebrew to install Git, you can use the native Mac OS X keystore with:

git config --global credential.helper osxkeychain

For Windows, there is a helper called Git Credential Manager for Windows or wincred in msysgit.

git config --global credential.helper wincred # obsolete

With Git for Windows 2.7.3+ (March 2016):

git config --global credential.helper manager

For Linux, you can use gnome-keyring(or other keyring implementation such as KWallet).

Finally, after executing one of the suggested command one time manually, you can execute your script without changes in it.

sdikby
  • 1,383
  • 14
  • 30
  • @clankill3r did you try what i suggested ? It would be benefic for all of us if your question gets good documented – sdikby Mar 15 '17 at 10:05
1

Use the following python code. This will import the os module in python and make a system call with sudo permissions.

#!/bin/python
import os 
os.system("sudo ./update.sh")
  • What happens if they want to use a user that isn't root? Or they want to do this without entering a password? – tahsmith Mar 15 '17 at 05:48
  • If the user isn't root then they will have to at least be a member of the sudo group. The shell script must also have executable permissions for the sudo group otherwise `sudo bash update.sh` would suffice. There are ways to do this without entering a password, however they are risky and i'd advice against it. – Alexander Collins Mar 16 '17 at 00:56