Scripting con amule

Amule logo

Tutti voi conoscerete eMule, il celebre client del protocollo eDonkey, forse il programma in assoluto più usato per scaricare ogni genere di file dalla rete peer to peer. Tuttavia il mulo non è da solo perché gli sviluppatori della comunità open source (nonostante eMule di fatto sia già open source) hanno creato aMule, un clone del fratello maggiore, forse meno completo dal punto di vista delle funzionalità, ma con alcuni pregi di tutto rispetto.

  • Funziona su tutti i sistemi operativi, mentre eMule esiste solo per Windows.
  • Può essere installato senza una interfaccia grafica (quindi adatto anche per i server).

Per questi due motivi ho installato aMule sul server di casa mia (con sistema operativo Linux), impostando le ricerche automatiche tramite alcuni script php/mysql e il demone (ovvero un programma costantemente attivato, nulla a che fare col demonio) cron.

Innanzi tutto occorre avere installato sul proprio server i demoni di amule (amuled) e cron (crond). Il secondo di solito è già attivo in ogni sistema Linux, mentre il secondo deve essere scaricato dal sito ufficiale www.amule.org, anche se si può trovare già incluso nelle repository di molte distribuzioni. Oltre a questi due programmi, è necessario il client amulecmd, che permette di gestire aMule da linea di comando. Il tutto è disponibile sul sito ufficiale del progetto.

amulecmd

L’interfaccia a linea di comando di aMule è di semplice utilizzo, almeno per i nerd cui lo schermo nero con le scrittine bianche non fa più paura. Per entrare è sufficiente invocare il comando amulecmd. Vi si presenterà una shell particolare, i cui principali comandi sono:

  • status: permette di visualizzare lo stato della connessione.
  • search: esegue una ricerca.
  • results: visualizza i risultati della precedente ricerca.
  • download: scarica un file.
  • show: visualizza lo stato dei download (e anche altre informazioni).

Per uscire e tornare alla shell bash cui siamo abituati, basta il solito Ctrl-D.

Un output tipico del comando status (che non ammette parametri) è il seguente

> ED2K: Connected to Razorback 3.3 [92.48.193.14:5000] with HighID
> Kad: Not running
> Download: 41.44 kB/s
> Upload: 53.93 kB/s
> Clients in queue: 501
> Total sources: 187

Per eseguire una ricerca, ad esempio della nota distribuzione openSuSE di Novell, possiamo eseguire il comando search global opensuse

aMulecmd$ search global opensuse
> Request failed with the following error: Search in progress. Refetch results in a moment!

Nonostante la risposta “request failed”, in realtà la ricerca è partita. La parola global indica che stiamo eseguendo la ricerca sui server. Utilizzando kad, la ricerca sarebbe avvenuta sulla rete Kademlia.

Con il comando results possiamo vedere i risultati

aMulecmd$ results

Nr.    Filename:                                                                        Size(MB):  Sources:
-----------------------------------------------------------------------------------------------------------
0.    openSUSE-11.0-Addon-Lang-i386-iso                                                 611.746     4
1.    openSUSE-11.0-DVD-i386.iso                                                       2318.894     1
2.    [peerates.net] - LINUX - US - OpenSuse - 10.x - Novell Reference Guide.pdf          6.855     1
3.    [PEERATES.NET] - US - EBook - Linux - OpenSuSE 10.x Reference.pdf                  11.420     2
4.    openSUSE-11.0-GNOME-LiveCD-i386-iso                                               664.100     3
5.    openSUSE-11.0-RC1-KDE4-LiveCD-i386-iso                                            645.644     1
6.    openSUSE-11.0-Addon-Lang-x86_64.iso                                               608.974     2
7.    Suse Opensuse Linux 10.2 Multilanguage Dvd x86.iso                               3701.256     4
> Number of search results: 8

Per scaricare il file, è sufficiente digitare il comando download # dove al posto di # va inserito il numero che precede la nostra scelta. Ad esempio download 4 scaricherà il file openSUSE-11.0-GNOME-LiveCD-i386-iso.

Per vedere lo stato di avanzamento dei download, basta digitare il comando show dl.

Lo script finale

Per integrare il tutto con php, occorre in pratica eseguire i comandi sopra descritti con il comodo costrutto

$output = `eseguimi`;

che esegue il comando eseguimi e salva nella variabile $output l’output del comando stesso. Il programma amulecmd viene quindi eseguito con l’opzione -c "comando" che esegue contestualmente anche comando all’interno di aMule.

Per facilitarmi nel compito, ho costruito una funzione scarica che mette in coda la ricerca di aMule e accetta un po’ di parametri:

  • $query è la stringa di testo della ricerca (ad esempio “opensuse”).
  • $search_delay è il ritardo, in secondi, dopo il quale la ricerca viene abbandonata se non ha trovato almeno $min_results risultati.
  • $min_results è il numero minimo di risultati per stabilire se una ricerca ha avuto successo.
  • $type può essere global oppure kad e stabilisce quale protocollo usare per la ricerca.

Ecco il codice sorgente della funzione:

function scarica($query, $search_delay = 50, $min_results = 5, $type = "global") {
  $query = ereg_replace("['&`\\"]", " ", $query);
  $output = `amulecmd -c "search $type $query"`;
  $i = 0;
  while (risultatiMulo() <= $min_results && $i < $search_delay) {
    $i++;
    sleep(1);
  }

  if ($i >= $search_delay) {
    return false;
  }
  $output = `amulecmd -c "results"`;
  $outrows = explode("n", $output);

  $newrows = array();
  foreach ($outrows as $riga) {
    if (ereg("^([0-9]+)\.[ ]*(.*)[ ]*([0-9]+\.[0-9]*)[ ]*([0-9]+)$", trim($riga), $ris)) {
      $newrows[] = $ris;
    }
  }
  usort($newrows, makeSortFunction("4", 1));

  $filename = "/tmp/".rand();
  $F = fopen($filename, "w");
  fwrite($F, "resultsndownload ".$newrows[0][1]);
  fclose($F);

  $log = `cat $filename | amulecmd`;

  unlink($filename);
  return $log;
}

Nel codice ho usato altre due funzioni, risultatiMulo e makeSortFunction che, rispettivamente, fanno il refresh dei risultati di aMule e ordinano un array multidimensionale di php rispetto a un indice stabilito. Qui di seguito i sorgenti:

function risultatiMulo() {
  if (ereg("search results: ([0-9]*)", `amulecmd -c "results"`, $res)) {
    return $res[1];
  }
  else {
    return 0;
  }
}

function makeSortFunction($field, $reverse = 0) {
  if ($reverse) {
    $code = "return strnatcmp($b['$field'], $a['$field']);";
  }
  else {
    $code = "return strnatcmp($a['$field'], $b['$field']);";
  }
  return create_function('$a,$b', $code);
}

Ora il grosso è fatto; non resta che creare lo script e inserirlo in cron. Ad esempio creiamo uno script suse.php che ogni settimana, alle 4 del mattino della domenica, scarica la distribuzione di Novell. Il file suse.php sarà del tipo:

<?php

# [qui ci andranno le funzioni...]
scarica("opensuse", 20, 10, "kad");

?>

per scaricare la distribuzione openSuSE, tentando per 20 secondi, iniziando se trova almeno 10 risultati, su rete Kademlia.

Infine, per fare sì che lo script venga eseguito ogni domenica notte alle 4 del mattino, basta digitare

crontab -e

e aggiungere nell’editor la riga

0 4 * * 0 php /path/dello/script/suse.php

Oplà, il gioco è fatto!

One thought on “Scripting con amule

  1. Facilissimo! Una traduzione in italiano?

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *