Tool MiniTool - Gestore di Source Server in Python (Building Manager)

Ikarus_

Utente Emerald
8 Settembre 2012
1,050
23
586
446
Ultima modifica:
Ho scritto questo piccolo tool in python per gestire tutte le operazioni fattibili su un sorgente server in un unico script da runnare.
Il tool è scritto in Python 2.7 ma dovrebbe avere totale portabilità anche in versioni successive.

Il tool permette di eseguire le seguenti azioni:
-Compilazioni:
Compilare game/db
Compilare game/db con clean
Compilare entrambi (consecutivamente)
Compilare entrambi con clean


-Touch (non verranno creati file vuoti se sbagliate a scrivere il nome del file):
Eseguire il Touch di uno o più file in game/src (inserendo solo i nomi dei file separati da uno spazio)
Eseguire il Touch di uno o più file in db/src (inserendo solo i nomi dei file separati da uno spazio)

-Strip:
Strippare game (copiandolo , conservando il file unstripped)
Strippare db (--same)



Additional features:
- Il tool rileva se un file è stato modificato $valore secondi nel futuro (se ad esempio non avete impostato correttamente la data della vostra macchina di compilazione) e vi informerà di ciò, chiedendovi anche se volete touchare il file oppure settare la data corretta della macchina (oppure di non fare nessuna delle due azioni ignorando il file)
- Il tool se tenta di strippare un file che non esiste vi chiederà se necessitate di compilarlo e (se scegliete si) avvierà la compilazione strippando il file al termine di essa.
- Il tool è scritto con python procedurale , non object-oriented , dovrebbe essere facile personalizzarlo in caso qualcuno voglia farlo.
- Potete avviare più di un comando in sequenza usando uno dei seguenti caratteri per dividere gli indici dei comandi : ("&&","&","|"," ",'\t',"-",',') (es. : 1&9 -> build game e strip game)
- Il tool può anche prendere in input da comandline le azioni da eseguire (vedi sotto per la lista di input conosciuti dal programma)


Da sapere:
- Per avviare uno script in python su una macchina bisogna aver installato python (in questo caso si consiglia il 27 giusto perchè garantito il funzionamento). Se non lo avete installato potete farlo facilmente con il pkg manager o con i ports.
- Per cambiare la versione di python da usare con lo script dovete modificare il percorso dell'eseguibile al primo rigo dello script.
- Non dovrebbero esserci modifiche fare allo script con nessun tipo di codice sorgente , per eventuali problemi relativi a qualche funzionalità dello script , potete postare sotto la discussione e vi sarà data soluzione al problema.
- Per usare i comandi dello script bisogna che l'utente che stiate usando sia root o abbia i permessi di root e che siano dati i permessi anche al file dello script.
- Per avviare lo script bisogna posizionarsi da shell nella directory dell script (usando il comando "cd (call directory)") e poi digitare il comando "./nomescript.py"
- Se create il file in cui incollare lo script da notepad++ potrebbe darsi che imposti come carattere di fine linea i caratteri terminatori di linea di windows , in tal caso da "Modifica" potrete trovare la voce per cambiarli in "Unix".
- Ho testato il file a fondo per ora , non ho trovato alcun errore , ma se doveste trovarne voi vi basterà segnalarli per ottenere la soluzione al problema.
- E' possibile disabilitare la domanda se si vuole uscire dallo script o meno semplicemente ponendo a False la costante definita a inizio script

Per qualunque problema vi invito a scrivere nei commenti della discussione piuttosto che contattarmi in privato , al fine che la discussione sulla risoluzione del vostro problema possa essere d'aiuto anche ad altri utenti.
Spero sia utile a qualcuno , byebye




E' possibile usarne anche più di uno separandoli da uno spazio.

Codice:
--build-game
--build-db
--build-game-clean
--build-db-clean
--build-all
--build-all-clean
--touch-file-gamesrc
--touch-file-dbsrc
--strip-game
--strip-db
--strip-all




Python:
#!/usr/local/bin/python2.7
import os
import time
import sys

ENABLE_ASK_BEFORE_EXIT = False
ENABLE_AUTOTOUCH = True

def get_revision_filename(file):
    if os.path.isfile("__REVISION__"):
        line = open("__REVISION__","r").readline()
        return file + "_r" + line.strip()

    else:
        return file



def check_last_edit(path):
    def check_last_edit_single_file(file):
        nowtime = time.time()
        lastedit = os.path.getmtime(file)
        if nowtime < lastedit:
            if ENABLE_AUTOTOUCH:
                touch_file("" , file)
                return
            ans = ""
            while ans == "":
                print("file [%s] has modified %s seconds in future. do you want to touch it or to change date?\nchoose:(touch/date/n)"%(file , int(lastedit-nowtime)))
                ans = raw_input().strip()
        
                if ans == 'n':
                    break
        
                if ans == 'touch':
                    touch_file("" , file)
        
                elif ans == 'date':
                    print("enter date (YYYYMMDDHHMM):")
                    mydate = raw_input().strip()
            
                    res = os.system("date %s"%mydate)
            
                    if not res in (0,512):
                        print("cannot set datetime. try another option.")
                        ans = ""
                        continue
            
                    nowtime = time.time()
        
                else:
                    print("unknown answer [%s]"%ans)
                    ans = ""

    #end of single file
    if path[-4:] != '/src' and path[-4:] != '\\src':
        path += "/src"

    common = "common"

    files = [path+"/"+file for file in os.listdir(path) if os.path.isfile(path+"/"+file)]
    files += [common+"/"+file for file in os.listdir(common) if os.path.isfile(common+"/"+file)]



    for file in files:
        check_last_edit_single_file(file)


def ask_if_exit():
    if not ENABLE_ASK_BEFORE_EXIT:
        print("exit!")
        sys.exit()


    print("do you want to stop the script operations?y/n\n")

    ans = ""
    while ans == "":
        ans = raw_input().strip()
        if ans == 'y':
            sys.exit()
            return
 
        elif ans == 'n':
            return
 
        else:
            print("unknow answer [%s] , try again"%(ans))
            print("do you want to stop the script operations?y/n\n(press just 'y' or 'n')\n")
            ans = ""


def close():
    print("bye bye")
    sys.exit()

def run_os_command(cmd):
    try:
        res = os.system(cmd)
        if res:
            print("cannot run os command [%s] error %s"%(cmd,str(res)))
            ask_if_exit()
            return False
    except Exception ,e:
        print("an exception during run os command [%s] exception[%s]"%(cmd,str(e)))
        ask_if_exit()
        return False

    return True

def strip_file(file):
    stripfile = file+"_s"
    sourcefile= get_revision_filename(file)

    if not os.path.isfile(file+"/"+sourcefile):
        print("cannot find source file [%s]"%(file+"/"+sourcefile))
        ans=""
 
        while ans == "":
            print("do you want to build it?y/n")
            ans = raw_input().strip()
            if ans == 'y':
                build_file(file)
                strip_file(file)
                return
    
            if ans == 'n':
                return
    
            else:
                print("unknown answer [%s] try again."%ans)
                ans = ""
        return

    if os.path.isfile("%s/%s"%(file,stripfile)):
        os.remove("%s/%s"%(file,stripfile))

    if not run_os_command("cp %s/%s %s/%s"%(file,sourcefile, file , stripfile)):
        return

    run_os_command("strip -s %s/%s"%(file,stripfile))

def strip_db():
    strip_file("db")

def strip_game():
    strip_file("game")

def strip_all():
    strip_db()
    strip_game()

def touch_file(dir , files = ""):
    if len(dir)>0 and dir[-1] != '\\' and dir[-1] != '/':
        dir += "/"

    if files != "":
        files = files.split(" ")
        for file in files:
            if not os.path.isfile(dir+file):
                print("cannot find the file required [%s]."%file)
                continue
    
            else:
                if not run_os_command("touch %s"%(dir + file)):
                    print("cannot find the file required [%s]."%file)
                    continue
        
                else:
                    print("touched %s"%file)
    else:
        print("the path [%s] will automatically added to the file path\nyou can use a space to separate the names to touch more one file"%(dir))
        ans = ""
        while ans == "":
            print("enter the names of the files (exit to exit):")
            ans = raw_input().strip()
    
            if ans == 'exit':
                print("You didn't touch any file.")
                ask_if_exit()
                return
    
            files = ans.split(' ')
    
            for file in files:
                if not os.path.isfile(dir+file):
                    print("cannot find the file required [%s]."%file)
                    if len(files) == 1:
                        ans = ""
                    continue
        
                else:
                    if not run_os_command("touch %s"%(dir + file)):
                        print("cannot find the file required [%s]."%file)
                        if len(files) == 1:
                            ans = ""
                        continue
            
                    else:
                        print("touched %s"%file)


def touch_in_db_src():
    touch_file("db/src")

def touch_in_game_src():
    touch_file("game/src")



def build_all():
    build_game()
    build_db()

def build_all_clean():
    build_game_clean()
    build_db_clean()


def build_file(file):
    check_last_edit(file)
    cmd = "cd %s/src && gmake && cd ../../"%file
    if not run_os_command(cmd):
        return

    output=get_revision_filename("%s/%s"%(file,file))
    if os.path.isfile(output):
        print("build %s successful."%output)

    else:
        print("cannot build file %s."%output)
        ask_if_exit()


def build_game():
    build_file("game")

def build_db():
    build_file("db")


def clean_build(file):
    return run_os_command("cd %s/src && gmake clean && cd ../../"%file) == True


def build_clean(file):
    if not clean_build(file):
        ask_if_exit()

    else:
        print("%s cleaned"%file)

    build_file(file)


def build_db_clean():
    build_clean("db")


def build_game_clean():
    build_clean("game")



EVENTS = {
    1: {
        "name" : "BUILD GAME",
        "event": build_game,
        "cmd" : "--build-game",
    },

    2: {
        "name" : "BUILD DB",
        "event": build_db,
        "cmd" : "--build-db",
    },

    3: {
        "name" : "BUILD GAME CLEAN",
        "event": build_game_clean,
        "cmd" : "--build-game-clean",
    },

    4: {
        "name" : "BUILD DB CLEAN",
        "event": build_db_clean,
        "cmd" : "--build-db-clean",
    },

    5:{
        "name" : "BUILD ALL",
        "event": build_all,
        "cmd" : "--build-all",
    },

    6: {
        "name" : "BUILD ALL CLEAN",
        "event": build_all_clean,
        "cmd" : "--build-all-clean",
    },

    7: {
        "name" : "TOUCH FILE IN game/src",
        "event": touch_in_game_src,
        "cmd" : "--touch-file-gamesrc",
    },

    8: {
        "name" : "TOUCH FILE db/src",
        "event": touch_in_db_src,
        "cmd" : "--touch-file-dbsrc",
    },

    9:{
        "name" : "STRIP GAME",
        "event": strip_game,
        "cmd" : "--strip-game",
    },

    10:{
        "name" : "STRIP DB",
        "event": strip_db,
        "cmd" : "--strip-db",
    },

    11:{
        "name" : "STRIP ALL",
        "event": strip_all,
        "cmd" : "--strip-all",
    },

    0:{
        "name" : "CLOSE",
        "event": close,
        "cmd" : "--close",
    },
}



def print_commandlist():
    print("What do you want to do?\n")
    toprint = [ (EVENTS[key]["name"],str(key)) for key in EVENTS]

    for thing in toprint: print("%s.\t%s"%(thing[1],thing[0]))


def do_cmd(cmd):
    key = int(cmd)
    if not key in EVENTS:
        print("Unknown command [%d] (ignored)\n")
        return

    print("executing [%s]..."%(EVENTS[key]["name"]))
    event = EVENTS[key]["event"]
    event()


def is_right_ans(ans):
    andchar = ("&&","&","|"," ",'\t',"-",',')
    return len([char for char in ans if not char in andchar and not char.isdigit()]) == 0



def do_commands(cmdstr):
    andchar = ("&&","&","|"," ",'\t',"-",',')
    cmdlist = [cmdstr]
    tmp = []

    for char in andchar:
        for cmd in cmdlist:
            tmp = list(cmdlist)
            cmdlist = []
    
            for part in tmp:
                cmdlist+= part.split(char)

    wrong = [cmd for cmd in cmdlist if not cmd.isdigit()]
    if len(wrong) != 0:
        print("found wrong command/commands [%s] (ignored)."%str(wrong))

    for cmd in cmdlist:
        if cmd in wrong:
            continue
 
        do_cmd(cmd)

def main():
    if len(sys.argv) > 1:
        cmdargs = [ (EVENTS[key]["cmd"] , key) for key in EVENTS]
    
        listofargs = [value["cmd"] for value in EVENTS.values()]
        wrongargs = [arg for arg in sys.argv if not arg in listofargs and arg != sys.argv[0]]
    
        if len(wrongargs) != 0:
            print("wrong args [%s] ignored."%(str(wrongargs)))
    
    
        for cmdarg in cmdargs:
            if cmdarg[0] in sys.argv and not cmdarg[0] in wrongargs:
                do_cmd(cmdarg[1])
    
        return
 
 
 
    print_commandlist()

    ans = ""
    while ans == "":
        ans = raw_input().strip()
        if not is_right_ans(ans):
            print("wrong input command.")
            print_commandlist()
            ans = ""
 
    do_commands(ans)





if __name__ == "__main__":
    main()
Messaggio unito automaticamente:

Risolto un errore riguardo il comando gmake clean
 
Ho scritto questo piccolo tool in python per gestire tutte le operazioni fattibili su un sorgente server in un unico script da runnare.
Il tool è scritto in Python 2.7 ma dovrebbe avere totale portabilità anche in versioni successive.

Il tool permette di eseguire le seguenti azioni:
-Compilazioni:
Compilare game/db
Compilare game/db con clean
Compilare entrambi (consecutivamente)
Compilare entrambi con clean


-Touch (non verranno creati file vuoti se sbagliate a scrivere il nome del file):
Eseguire il Touch di uno o più file in game/src (inserendo solo i nomi dei file separati da uno spazio)
Eseguire il Touch di uno o più file in db/src (inserendo solo i nomi dei file separati da uno spazio)

-Strip:
Strippare game (copiandolo , conservando il file unstripped)
Strippare db (--same)



Additional features:
- Il tool rileva se un file è stato modificato $valore secondi nel futuro (se ad esempio non avete impostato correttamente la data della vostra macchina di compilazione) e vi informerà di ciò, chiedendovi anche se volete touchare il file oppure settare la data corretta della macchina (oppure di non fare nessuna delle due azioni ignorando il file)
- Il tool se tenta di strippare un file che non esiste vi chiederà se necessitate di compilarlo e (se scegliete si) avvierà la compilazione strippando il file al termine di essa.
- Il tool è scritto con python procedurale , non object-oriented , dovrebbe essere facile personalizzarlo in caso qualcuno voglia farlo.
- Potete avviare più di un comando in sequenza usando uno dei seguenti caratteri per dividere gli indici dei comandi : ("&&","&","|"," ",'\t',"-",',') (es. : 1&9 -> build game e strip game)


Da sapere:
- Per avviare uno script in python su una macchina bisogna aver installato python (in questo caso si consiglia il 27 giusto perchè garantito il funzionamento). Se non lo avete installato potete farlo facilmente con il pkg manager o con i ports.
- Per cambiare la versione di python da usare con lo script dovete modificare il percorso dell'eseguibile al primo rigo dello script.
- Non dovrebbero esserci modifiche fare allo script con nessun tipo di codice sorgente , per eventuali problemi relativi a qualche funzionalità dello script , potete postare sotto la discussione e vi sarà data soluzione al problema.
- Per usare i comandi dello script bisogna che l'utente che stiate usando sia root o abbia i permessi di root e che siano dati i permessi anche al file dello script.
- Per avviare lo script bisogna posizionarsi da shell nella directory dell script (usando il comando "cd (call directory)") e poi digitare il comando "./nomescript.py"
- Se create il file in cui incollare lo script da notepad++ potrebbe darsi che imposti come carattere di fine linea i caratteri terminatori di linea di windows , in tal caso da "Modifica" potrete trovare la voce per cambiarli in "Unix".
- Ho testato il file a fondo per ora , non ho trovato alcun errore , ma se doveste trovarne voi vi basterà segnalarli per ottenere la soluzione al problema.
- E' possibile disabilitare la domanda se si vuole uscire dallo script o meno semplicemente ponendo a False la costante definita a inizio script

Per qualunque problema vi invito a scrivere nei commenti della discussione piuttosto che contattarmi in privato , al fine che la discussione sulla risoluzione del vostro problema possa essere d'aiuto anche ad altri utenti.
Spero sia utile a qualcuno , byebye



Python:
#!/usr/local/bin/python2.7
import os
import time
import sys

ENABLE_ASK_BEFORE_EXIT = True

def get_revision_filename(file):
if os.path.isfile("__REVISION__"):
line = open("__REVISION__","r").readline()
return file + "_r" + line.strip()

else:
return file



def check_last_edit(path):
def check_last_edit_single_file(file):
nowtime = time.time()
lastedit = os.path.getmtime(file)
if nowtime < lastedit:
ans = ""
while ans == "":
print("file [%s] has modified %s seconds in future. do you want to touch it or to change date?\nchoose:(touch/date/n)"%(file , int(lastedit-nowtime)))
ans = raw_input().strip()

if ans == 'n':
break

if ans == 'touch':
touch_file("" , file)

elif ans == 'date':
print("enter date:")
mydate = raw_input().strip()

res = os.system("date %s"%mydate)

if not res in (0,512):
print("cannot set datetime. try another option.")
ans = ""
continue

nowtime = time.time()

else:
print("unknown answer [%s]"%ans)
ans = ""

#end of single file
if path[-4:] != '/src' and path[-4:] != '\\src':
path += "/src"

common = "common"

files = [path+"/"+file for file in os.listdir(path) if os.path.isfile(path+"/"+file)]
files += [common+"/"+file for file in os.listdir(common) if os.path.isfile(common+"/"+file)]



for file in files:
check_last_edit_single_file(file)


def ask_if_exit():
if not ENABLE_ASK_BEFORE_EXIT:
print("exit!")
sys.exit()


print("do you want to stop the script operations?y/n\n")

ans = ""
while ans == "":
ans = raw_input().strip()
if ans == 'y':
sys.exit()
return

elif ans == 'n':
return

else:
print("unknow answer [%s] , try again"%(ans))
print("do you want to stop the script operations?y/n\n(press just 'y' or 'n')\n")
ans = ""


def close():
print("bye bye")
sys.exit()

def run_os_command(cmd):
try:
res = os.system(cmd)
if res:
print("cannot run os command [%s] error %s"%(cmd,str(res)))
ask_if_exit()
return False
except Exception ,e:
print("an exception during run os command [%s] exception[%s]"%(cmd,str(e)))
ask_if_exit()
return False

return True

def strip_file(file):
stripfile = file+"_s"
sourcefile= get_revision_filename(file)

if not os.path.isfile(file+"/"+sourcefile):
print("cannot find source file [%s]"%(file+"/"+sourcefile))
ans=""

while ans == "":
print("do you want to build it?y/n")
ans = raw_input().strip()
if ans == 'y':
build_file(file)
strip_file(file)
return

if ans == 'n':
return

else:
print("unknown answer [%s] try again."%ans)
ans = ""
return

if os.path.isfile("%s/%s"%(file,stripfile)):
os.remove("%s/%s"%(file,stripfile))

if not run_os_command("cp %s/%s %s/%s"%(file,sourcefile, file , stripfile)):
return

run_os_command("strip -s %s/%s"%(file,stripfile))

def strip_db():
strip_file("db")

def strip_game():
strip_file("game")

def strip_all():
strip_db()
strip_game()

def touch_file(dir , files = ""):
if len(dir)>0 and dir[-1] != '\\' and dir[-1] != '/':
dir += "/"

if files != "":
files = files.split(" ")
for file in files:
if not os.path.isfile(dir+file):
print("cannot find the file required [%s]."%file)
continue

else:
if not run_os_command("touch %s"%(dir + file)):
print("cannot find the file required [%s]."%file)
continue

else:
print("touched %s"%file)
else:
print("the path [%s] will automatically added to the file path\nyou can use a space to separate the names to touch more one file"%(dir))
ans = ""
while ans == "":
print("enter the names of the files (exit to exit):")
ans = raw_input().strip()

if ans == 'exit':
print("You didn't touch any file.")
ask_if_exit()
return

files = ans.split(' ')

for file in files:
if not os.path.isfile(dir+file):
print("cannot find the file required [%s]."%file)
if len(files) == 1:
ans = ""
continue

else:
if not run_os_command("touch %s"%(dir + file)):
print("cannot find the file required [%s]."%file)
if len(files) == 1:
ans = ""
continue

else:
print("touched %s"%file)


def touch_in_db_src():
touch_file("db/src")

def touch_in_game_src():
touch_file("game/src")



def build_all():
build_game()
build_db()

def build_all_clean():
build_game_clean()
build_db_clean()


def build_file(file):
check_last_edit(file)
cmd = "cd %s/src && gmake && cd ../../"%file
if not run_os_command(cmd):
return

output=get_revision_filename("%s/%s"%(file,file))
if os.path.isfile(output):
print("build %s successful."%output)

else:
print("cannot build file %s."%output)
ask_if_exit()


def build_game():
build_file("game")

def build_db():
build_file("db")


def clean_build(file):
return run_os_command("cd %s/src && gmake clean && cd ../../"%file) == True


def build_clean(file):
if not clean_build(file):
ask_if_exit()

else:
print("%s cleaned"%file)

build_file(file)


def build_db_clean():
build_clean("db")


def build_game_clean():
build_clean("game")



EVENTS = {
1: {
"name" : "BUILD GAME",
"event": build_game,
},

2: {
"name" : "BUILD DB",
"event": build_db,
},

3: {
"name" : "BUILD GAME CLEAN",
"event": build_game_clean,
},

4: {
"name" : "BUILD DB CLEAN",
"event": build_db_clean,
},

5:{
"name" : "BUILD ALL",
"event": build_all,
},

6: {
"name" : "BUILD ALL CLEAN",
"event": build_all_clean,
},

7: {
"name" : "TOUCH FILE IN game/src",
"event": touch_in_game_src,
},

8: {
"name" : "TOUCH FILE db/src",
"event": touch_in_db_src,
},

9:{
"name" : "STRIP GAME",
"event": strip_game,
},

10:{
"name" : "STRIP DB",
"event": strip_db,
},

11:{
"name" : "STRIP ALL",
"event": strip_all,
},

0:{
"name" : "CLOSE",
"event": close,
},
}



def print_commandlist():
print("What do you want to do?\n")
toprint = [ (EVENTS[key]["name"],str(key)) for key in EVENTS]

for thing in toprint: print("%s.\t%s"%(thing[1],thing[0]))


def do_cmd(cmd):
key = int(cmd)
if not key in EVENTS:
print("Unknown command [%d] (ignored)\n")
return

print("executing [%s]..."%(EVENTS[key]["name"]))
event = EVENTS[key]["event"]
event()


def is_right_ans(ans):
andchar = ("&&","&","|"," ",'\t',"-",',')
return len([char for char in ans if not char in andchar and not char.isdigit()]) == 0



def do_commands(cmdstr):
andchar = ("&&","&","|"," ",'\t',"-",',')
cmdlist = [cmdstr]
tmp = []

for char in andchar:
for cmd in cmdlist:
tmp = list(cmdlist)
cmdlist = []

for part in tmp:
cmdlist+= part.split(char)

wrong = [cmd for cmd in cmdlist if not cmd.isdigit()]
if len(wrong) != 0:
print("found wrong command/commands [%s] (ignored)."%str(wrong))

for cmd in cmdlist:
if cmd in wrong:
continue

do_cmd(cmd)

def main():
print_commandlist()

ans = ""
while ans == "":
ans = raw_input().strip()
if not is_right_ans(ans):
print("wrong input command.")
print_commandlist()
ans = ""

do_commands(ans)





if __name__ == "__main__":
main()
Messaggio unito automaticamente:

Risolto un errore riguardo il comando gmake clean
Mi hai battuto a tempo.
Scherzo, stavo lavorando ad una cosa simile ma direttamente dallo script che ho fatto per avvio e chiusura serve.
Anyway hai fatto davvero un bel lavoro.
 
  • Mi piace
Reazioni: Ikarus_
Ultima modifica:
Aggiunta la possibilità di passare direttamente da comando le azioni da fare (optional)
Se ne possono passare anche più di una separadole da uno spazio
Esempio di utilizzo (usare gli argomenti da shell è solo un opzione , altrimenti si può sempre fare tramite scelta da lista di azioni)
./nomescript.py --build-game --strip-game
 
va messo nella cartella insieme a "common", "db", "game" ecc. (in genere questa cartella si chiama "Server") e lo runni da comando (./nomescript.py) dopo avergli dato gli ottali.