Sida 1 av 2
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:53
av Konservburk
1. Inledning
Inställningsmöjligheterna i rtorrent är egentligen ingen hemlighet även om informationen av någon anledning tycks vara höljd i dunkel. Det går faktiskt att få till betydligt mer sofistikerade och avancerade lösningar i ~/.rtorrent.rc än vad manualbladet ger sken av.
Här tänker jag ta upp sådant som egentligen inte finns ordentligt dokumenterat, varken i manualbladet eller på rtorrents wiki-sidor. Jag har istället studerat källkoden till rtorrent-0.8.4 för att ta reda på hur det hela hänger ihop. Förmodligen gäller mycket av detta även andra versioner, men det är långt ifrån säkert.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:53
av Konservburk
2. Grundläggande syntax
Varje enskild rad i
~/.rtorrent.rc är ett helt eget separat
rtorrent-kommando. Dessa inleds alltid med själva kommandonamnet följt av ett likhetstecken och därefter en argumentlista med noll eller flera kommaseparerade argument.
Kod: Markera allt
kommando_namn = argument_0, argument_1, argument_2, argument_3
Vad som i en vanlig
~/.rtorrent.rc ser ut att vara enkla tilldelningar är egentligen inget annat än
rtorrent-kommandon med ett enda argument.
Det mest komplicerade kommandot som vanligtvis används är
schedule som tar exakt fyra argument där det fjärde inte är något mindre än ett fullständigt
rtorrent-kommando med en helt egen argumentlista. Här uppstår genast problemet att
rtorrent måste kunna förstå vilka argument som hör till vilken argumentlista. Detta innebär att det inre kommandot måste escape:as på ett eller annat sätt. Det är nu det börjar bli intressant.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:53
av Konservburk
3. Fnuttologi
För att detta inte ska bli alltför förvirrande så inför jag begreppet escape-nivåer, där nivå-A är kommandon som inte behöver escape:as, nivå-B kommandon som behöver escape:as en gång, osv.
I en vanlig simpel
~/.rtorrent.rc är det mesta nivå-A och en del nivå-B. I undantagsfall förekommer även nivå-C, men i princip aldrig djupare än så. Här kommer vi dock att nosa oss ända in till som mest nivå-G.
Den grundläggande escape-varianten är att sätta ett backslash framför varje enskilt tecken som
rtorrent tolkar som något annat än som en del av en sträng. Det stora problemet är även backslash måste escape:as på detta sätt, vilket medför att antalet backslash-tecken som behövs växer exponentiellt med escape-nivån. I nivå-C behövs t.ex. tre backslash för varje tecken som ska escape:as. Det första escape:ar det andra som i sin tur följer med ut en nivå, och det tredje escape:ar själva tecknet som egentligen skulle escape:as. Den exakta formeln för antalet backslash som behövs är
2^(escape-nivån)-1:
- A: 2^0 - 1 = 0
B: 2^1 - 1 = 1
C: 2^2 - 1 = 3
D: 2^3 - 1 = 7
E: 2^4 - 1 = 15
F: 2^5 - 1 = 31
G: 2^6 - 1 = 63
En alternativ metod är att omge hela nivå-B med dubbelfnuttar. Ska även nivå-C escape:as på detta sätt så måste dubbelfnuttarna i sig escape:as med backslash, vilket innebär att vi egentligen bara har skjutit upp problemet en nivå. Å andra sidan så kan två escape:ade dubbelfnuttar i sig escape:a många andra tecken.
Nu har det blivit läge för ett illustrerande exempel. I följande o-escape:ade
rtorrent-kommando indikeras den önskade nivån av bokstäverna och argumentnumren av siffrorna:
Kod: Markera allt
A = a0, B = b0, C = c0, c1, D = d0, d1, d2, d3, c3, b2, a2
De två olika sätten att escape:a kommandot på blir som följer:
Kod: Markera allt
A=a0,B=b0\,C=c0\\\,c1\\\,D=d0\\\\\\\,d1\\\\\\\,d2\\\\\\\,d3\\\,c3\,b2,a2
Kod: Markera allt
A = a0, "B = b0, \"C = c0, c1, \\\"D = d0, d1, d2, d3\\\", c3\", b2", a2
Eftersom även mellanrummen måste escape:as så har jag skippat dem helt i den rena backslash-metoden. De behövs egentligen inte. Fördelen med fnutt-metoden är att de blir escape:ade på köpet och därför kan få vara kvar för att öka läsligheten.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:53
av Konservburk
4. Fördjupad fnuttologi
Vilken escape-metod som resulterar i flest backslash och därför bör undvikas varierar helt beroende på hur kommandot ser ut, nivån och antalet argument. För nivå-B är det ganska likvärdigt oavsett argumentantalet:
Kod: Markera allt
B=
B=b0
B=b0\,b1
B=b0\,b1\,b2
B=b0\,b1\,b2\,b3
Kod: Markera allt
"B ="
"B = b0"
"B = b0, b1"
"B = b0, b1, b2"
"B = b0, b1, b2, b3"
Jämför det med nivå-E där den rena backslash-metoden är klart bättre för kommandon med få argument, men klart sämre för kommandon med många argument:
Kod: Markera allt
E=
E=e0
E=e0\\\\\\\\\\\\\\\,e1
E=e0\\\\\\\\\\\\\\\,e1\\\\\\\\\\\\\\\,e2
E=e0\\\\\\\\\\\\\\\,e1\\\\\\\\\\\\\\\,e2\\\\\\\\\\\\\\\,e3
Kod: Markera allt
\\\\\\\"E =\\\\\\\"
\\\\\\\"E = e0\\\\\\\"
\\\\\\\"E = e0, e1\\\\\\\"
\\\\\\\"E = e0, e1, e2\\\\\\\"
\\\\\\\"E = e0, e1, e2, e3\\\\\\\"
Generellt så är fnutt-metoden alltid sämre när det gäller kommandon med färre än två argument. På samma sätt är den rena backslash-metoden alltid sämre för kommandon med fler än två argument. Den trenden blir tydligare och tydligare ju djupare nivå man kommer till. Ta nivå-G som ett sista avskräckande exempel:
Kod: Markera allt
G=
G=g0
G=g0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\,g1
Kod: Markera allt
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"G =\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"G = g0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"G = g0, g1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:54
av Konservburk
5. Övrig syntax
Det finns egentligen bara ytterligare en viktig sak att känna till. I vanliga fall skickas den inre nivån vidare som en oförändrad sträng till den yttre nivåns argument. Det är sedan upp till det yttre kommandot att avgöra om strängen ska tolkas som ett rtorrent-kommando som ska köras eller som en helt vanlig sträng. Det finns dock ett viktigt undantag. Om det absolut första tecknet i strängen som utgör en nivå är ett dollartecken så kommer nivån alltid att köras som ett kommando och det blir istället resultatet av det kommandot som skickas vidare till den yttre nivåns argument.
Kommandon kan dessutom separeras med semikolon och grupperas med krullparanteser. Det fungerar dock inte överallt, vilket egentligen inte är något problem eftersom det i princip aldrig varken är nödvändigt att kunna separera eller gruppera kommandon.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:54
av Konservburk
6. Att definiera egna rtorrent-kommandon
Det ännu odokumenterade
rtorrent-kommandot
system.method.insert används för att skapa helt egna
rtorrent-kommandon. Det första argumentet anger kommando-namnet som man kan välja helt själv. Det andra argumentet avgör vilken typ av kommando det rör sig om. Det finns flera olika varianter, men de mest intressanta är
value och
const_simple.
Detta skapar ett kommando av typen
value med namnet
return som inte tar några argument. I samma veva skapas även kommandot
return.set som tar ett argument och kan användas för att sätta värdet som returneras av
return. Inte speciellt spännande, men mycket användbart.
Nu tar vi istället en närmare titt på typen
const_simple. De resterande argumenten är fullständiga
rtorrent-kommandon som körs när det egenvalda kommandonamnet anropas.
Kod: Markera allt
system.method.insert = \
d.stop_and_close \
, const_simple \
, d.stop= \
, d.set_ignore_commands=1 \
, d.close=
Här har jag döpt mitt kommando till
d.stop_and_close, som i tur och ordning kommer att anropa
rtorrent-kommandona
d.stop=,
d.set_ignore_commands=1 och
d.close=, vilket är samma sak som händer när man trycker
ctrl-k. Det inledande "
d." indikerar att kommandot bara kan köras om det är associerat med en faktiskt torrent. På samma sätt måste kommandon som börjar med "
f." vara associerade med en faktisk fil, kommandon som börjar med "
t." med en tracker och "
p." med en peer. Exakt hur man associerar kommandon med faktiska torrenter, filer, trackers, och peers tar jag upp senare.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:54
av Konservburk
7. Villkor och argument
Ett av de för oss mest användbara
rtorrent-kommandona är
branch, vars första argument är ett villkor som avgör om det andra eller tredje argumentet ska köras. Finns det fler än tre argument så avgör det tredje argumentet om det fjärde eller femte ska köras, osv. Men för att verkligen kunna få till riktigt användbara villkor så vill man först kunna ta reda på vilka argument som det egna kommandot har tagit emot. För att göra det så använder man sig av
rtorrent-kommandona
argument.0,
argument.1 osv. Det kan se ut ungefär så här:
Kod: Markera allt
system.method.insert = \
try_run_arg \
, const_simple \
, " branch = \
\" \
or = \
\\\" \
less = \
argument.0= \
, cat=placeholder \
\\\" \
, \\\" \
less = \
cat=placeholder \
, argument.0= \
\\\" \
\" \
, $argument.0= \
"
Det går ut på att jag vill köra det första argumentet bara om det inte råkar vara lika med strängen
placeholder, som är standardvärdet för osatta argument. Ett lustigt sätt att få till ett likhetstest kan tyckas, men det är så man får göra när det inte finns annat än
or och
less att tillgå. Eftersom kommandot
less förväntar sig att argumenten i sig är kommandon så måste vi använda oss av kommandot
cat för att kunna få med
placeholder som en sträng. Det är även därför som
argument.0 saknar ett inledande dollartecken när det är argument till just
less.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:54
av Konservburk
8. Returvärden
För att kunna få tillbaka returvärden kan vi använda oss av
return som vi redan skapat tidigare. Men för att det inte ska bli så mycket strul varje gång det behövs ett returvärde så ordnar vi ett separat kommando som hanterar den biten:
Kod: Markera allt
system.method.insert = \
evaluate \
, const_simple \
, " branch = \
$argument.1= \
, return.set=false \
, return.set=true \
" \
, " branch = \
$argument.0= \
, return.set=$not=$return= \
" \
, " branch = \
return= \
, try_run_arg=$argument.2= \
, try_run_arg=$argument.3= \
"
Här avgör
argument.1 om returvärdet blir sant eller falskt, medan
argument.0 avgör om returvärdet ska vara inverterat eller inte, vilket bara är en bekvämlighetsgrej för att slippa använda kommandot
not när vårt nya kommando
evaluate anropas och på så sätt kunna undvika en extra escape-nivå. Returvärdet får tillslut avgöra om
argument.2 eller
argument.3 ska köras. Eftersom det inte är säkert att något av dessa argument ens har blivit satta så får vi nu användning för vårt tidigare kommando
try_run_arg.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:55
av Konservburk
9. Wrapper-kommandon
Det har blivit dags att börja dra lite nytta av alla mödor med
evaluate-kommandot. Först ett relativt enkelt wrapper-kommando runt kommandot
less, vilket egentligen inte är något märkvärdigare än att slå in
less-kommandot i lite kod som ser till så att
less alltid får vettig indata och ger vettig utdata tillbaka.
Kod: Markera allt
system.method.insert = \
require \
, const_simple \
, " branch = \
not=$argument.1= \
, require=0\\\,0 \
, not=$argument.0= \
, require=0 \
, \" \
evaluate = \
, \\\"$ \
less = \
return.set=$argument.0= \
, return.set=$argument.1= \
\\\" \
\" \
"
Egentligen inga konstigheter. Först sätts standardvärden för
argument.1 och
argument.0 om de skulle råka var tomma. Sedan jämförs argumenten med varandra och eftersom vi har ett inledande dollartecken så skickas resultatet av snarare än hela
less-kommandot vidare till
evaluate-kommandot. En slamkrypare är att
return.set i det här fallet inte har någonting med returvärdet att göra. Den biten hanteras ju av
evaluate som på grund av dollartecknet ens kommer att se
return.set. Det är istället så att
return.set i det här fallet är ett smart sätt att tvinga fram en konvertering från sträng till tal, vilket innebär att det går att anropa det nya
require-kommandot på ett betydligt smidigare sätt än vad som annars skulle ha varit möjligt.
Nu går det t.ex. att köra
require=$d.get_ratio=,1000,d.close= för att stänga en torrent om den har en ratio på minst 1. Och nu tänker du genast att det ju redan finns speciella kommandon för att göra just det. Det stämmer bra, men det här är betydligt smidigare eftersom vi även kan anropa
require med andra argument än
d.get_ratio och
d.close utan några svårigheter.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:55
av Konservburk
10. Externa villkor
Nu har vi kommit fram till en punkt där rtorrents interna kommandon inte längre räcker till för det jag vill åstadkomma. I det här fallet handlar det om sträng-matchning, vilket kan vara mycket användbart, men som sagt kräver ett externt kommando:
Kod: Markera allt
system.method.insert = \
match \
, const_simple \
, " evaluate = \
, \"$ execute_raw_nothrow = \
sh \
, -c \
, \\\" \
printf %s \\\\\\\"$0\\\\\\\" | \
grep -qE \\\\\\\"$1\\\\\\\" \
\\\" \
, $argument.0= \
, $argument.1= \
\" \
"
Det externa kommando som har används är inget annat än en omskrivning av det enkla skriptet:
Jag hade i princip kunnat använda vilket matchningskommando som helst, t.ex.
awk,
sed,
perl eller varför inte
expr. Men nu blev det
grep den här gången.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:55
av Konservburk
11. En första tillämpning
Nu har vi kommit fram till ett läge där det faktiskt går att få till något som är fullt användbart. Tanken är att använda det nya
match-kommandot för att testa om om en ny torrent hör till en viss speciell tracker, och utifrån den informationen sätta vilken katalog torrenten sedan laddas ner till.
Kommandot för att ta reda på tracker-adresssen är
t.get_url, vilket som tidigare nämnts kräver att kommandot associeras med en tracker. För att lyckas med det använder vi oss av kommandot
t.multicall som kör kommandon associerade med var och varje tracker för en given torrent.
Kod: Markera allt
system.method.insert = \
d.match_tracker \
, const_simple \
, " match = \
\"$ t.multicall = \
, t.get_url= \
\" \
, $argument.0= \
, $argument.1= \
, $argument.2= \
"
Här skickas de olika argumenten helt enkelt bara vidare till
match utan några konstigheter. Svårare än så här blev det faktiskt inte. Nu gäller det bara att koppla vårt nya
d.match_tracker-kommando så att det körs för varje ny torrent som laddas in. För att lyckas med det använder vi oss av kommandot
system.method.set_key med argumentet
event.download.inserted_new, vilket talar om att vi vill göra någonting just när en ny torrent laddas in:
Kod: Markera allt
system.method.set_key = event.download.inserted_new , filter_ubuntu \
, " d.match_tracker = (torrent\\\\\\\.ubuntu\\\\\\\.com) \
, d.set_directory_base=/media/linux-images/ \
"
Här sätts nerladdningskatalogen till
/media/linux-images/ om tracker-namnet innehåller
torrent.ubuntu.com, men inte annars. Punkterna behöver egentligen inte escape:as eftersom de matchar vilket tecken som helst, t.ex. en punkt. Men jag tog ändå med dem för att visa hur många backslash det egentligen ska vara.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:55
av Konservburk
12. Mer avancerade villkor
Det har blivit dags att använda
match-kommandot till sin fulla potential. Låt oss börja med ett kommando som vi kallar
d.require_seeds där vi helt enkelt kräver att torrenten har ett visst antal seeders samt att antalet seeders är minst lika stort som antalet leechers. Vi använder oss även denna gång av
t.multicall-kommandot, samt
return.set för att konvertera sträng till tal.
Kod: Markera allt
system.method.insert = \
d.require_seeds \
, const_simple \
, " match = \
\"$ t.multicall = \
, \\\" \
or = \
\\\\\\\" \
less = \
t.get_scrape_complete= \
, t.get_scrape_incomplete= \
\\\\\\\" \
, \\\\\\\" \
less = \
t.get_scrape_complete= \
, return.set=$argument.0= \
\\\\\\\" \
\\\" \
\" \
, 0 \
, $argument.1= \
, $argument.2= \
"
Efersom
t.multicall kör villkoret för alla trackers som hör ihop med torrenten, så kan det bli fler än ett resultat. Tricket här är att matcha mot något av dem, dvs ett slags
any-kommando. Hur man gör för att få till ett
all-kommando där alla villkor måste stämma illustrerar jag med ytterligare ett användbart exempel. Den här gången vill jag ta reda på om en torrent är färdignerladdad med hänsyn tagen till det faktum att man faktiskt kan välja bort delar av en torrent som man inte är intresserad av.
Kod: Markera allt
system.method.insert = \
d.completed \
, const_simple \
, " match = \
\"$ f.multicall = \
, \\\" \
and = \
f.get_priority= \
, \\\\\\\" \
less = \
f.get_completed_chunks= \
, f.get_size_chunks= \
\\\\\\\" \
\\\" \
\" \
, 1 \
, \
, \
" \
, " evaluate = \
, $return= \
, $argument.0= \
, $argument.1= \
" \
Den här gången använde jag
f.multicall och undersöker ifall varje fil är antingen helt nerladdad eller har en prioritet som är satt till
off. Själva matchningen är egentligen sig helt lik, fast omvänd. Jag matchar mot att någon av filerna inte är klar. För att sedan åter igen vända på steken och få till
all-villkoret så använder jag mig av vårt
evaluate-kommando på returvärdet. Kanske inte helt uppenbart, men det fungerar bra.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:56
av Konservburk
13. Köra kommandon på flera olika torrents
Vi har redan tidigare använt oss av kommandona
t.multicall och
f.multicall för att kunna köra tracker- respektive fil-associerade kommandon för flera trackers och filer på en gång. Motsvarande kommando för torrents är
d.multicall, men eftersom varje torrent har en individuell inställning som indikerar om torrenten i fråga verkligen vill lyda kommandon eller inte så vill vi inte köra
d.multicall rakt av utan att ta hänsyn till just detta.
Kod: Markera allt
system.method.insert = \
select_heed \
, const_simple \
, " d.multicall = \
$argument.0= \
, \" \
branch = \
d.get_ignore_commands= \
, return.set=false \
, \\\" \
evaluate = \
not= \
, \\\\\\\"$ \
branch = \
argument.1= \
, argument.1= \
, not= \
\\\\\\\" \
\\\" \
\" \
"
Den första argumentet till
d.multicall avgör för vilken grupp av torrenter det följande kommandot ska gälla. Om man inte anger något speciellt så blir det alla, men man skulle t.ex. kunna nöja sig med bara de som är startade. Här är vi dock generella och skickar vidare just det argumentet. Att jag använder ett
branch-kommando i
evaluate-kommandot istället för
argument.1 direkt har att göra med hur jag vill att ett tomt
argument.1 ska bete sig.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:56
av Konservburk
14. Faktisk användning av det vi hittills gjort
Tanken är att få till ett kommando som stänger färdiga torrenter så fort de får minst 1 i ratio, men bara om det finns minst lika många seeders som leechers och minst 3 seeders. Vi vill däremot inte att torrenter som är satta till
ignore_commands ska stängas av, varför det nya
select_heed-kommandot nu kommer väl till pass. Här räcker det dock inte med att skicka med resultatet av vårt förutsatta kombinerade villkor. Anledningen är att testet måste utföras för varje torrent som
d.multicall väljer ut. Det är egentligen inte mer komplicerat än vad vi gjort innan, men det kräver fler escape-nivåer, och vi kommer få nytta av den inledande fnuttologin:
Kod: Markera allt
system.method.insert = \
completed_dual_filter \
, const_simple \
, " select_heed = \
$argument.0= \
, \"$ cat = \
\\\" \
and = \
\\\\\\\" \
return = \
\\\\\\\\\\\\\\\"$ \
\\\" \
, $argument.1= \
, \\\" \
, \
, \
\\\\\\\\\\\\\\\" \
\\\\\\\" \
, \\\\\\\" \
return = \
\\\\\\\\\\\\\\\"$ \
\\\" \
, $argument.2= \
, \\\" \
, \
, \
\\\\\\\\\\\\\\\" \
\\\\\\\" \
, \\\\\\\" \
return = \
\\\\\\\\\\\\\\\"$ \
d.completed = \
, \
\\\\\\\\\\\\\\\" \
\\\\\\\" \
\\\" \
\" \
, $argument.3= \
, \
"
Av de tre villkoren valde jag att bara hårdkoda
d.completed, och istället skicka med de andra som argument. Anledningen är att vi då kan återanvända kommandot till annat senare. Det blir en förhållandevis enkelt kommando för att faktiskt skicka med de båda extra villkoren.
Kod: Markera allt
system.method.insert = \
on_ratio_and_seeds \
, const_simple \
, " completed_dual_filter = \
$argument.0= \
, \"$ cat = \
require=$d.get_ratio= \
, \\\\\\\, \
, $argument.1= \
\" \
, \"$ cat = \
d.require_seeds= \
, $argument.2= \
\" \
"
Nu är det bara kvar att binda vårt nya mästerverk med
schedule-kommandot så att det körs med jämna mellanrum:
Kod: Markera allt
schedule = close_on_ratio_and_seeds , 10 , 60 \
, " on_ratio_and_seeds = \
started \
, 1000 \
, 3 \
, d.stop_and_close= \
"
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:56
av Konservburk
15. Räkneoperationer
Det finns inget inbyggt kommando som kan räkna så vi behöver precis som med
match-kommandot använda oss av extern hjälp. Den här gången blir det dock betydligt mer komplicerat eftersom vi faktiskt vill kunna ta till var på resultatet och inte bara göra ett simpelt test. Jag har valt att använda mig av ett filrör, en så kallad
fifo. Det är ett utmärkt tillfälle att introducera ytterligare en kommando-typ, nämligen
static_const_string. Eftersom den är
static_const så måste vi initiera värdet direkt när vi deklarerar den genom det tredje argumentet.
Kod: Markera allt
system.method.insert = fifo , static_const_string \
, "$ cat = /var/run/rtorrent. , $system.pid= , .fifo"
Jag har valt att använda
awk för att utföra själva beräkningarna. Det är åter igen ett godtyckligt val från min sida som i princip kan ersättas med vilket annat kommando som helst som klarar av att räkna. För att läsa av
fifo:n och få tillbaka returvärdet så använder jag
rtorrent-kommandot
import.
Kod: Markera allt
system.method.insert = \
arithmetic \
, const_simple \
, " execute_raw_nothrow = \
sh \
, -c \
, \"$ cat = \
\\\" \
mkfifo \\\\\\\"$0\\\\\\\"; \
echo return.set= | awk '{print$0( \
\\\" \
, $argument.0= \
, \\\" \
)}' >\\\\\\\"$0\\\\\\\" && \
rm -f \\\\\\\"$0\\\\\\\" & \
\\\" \
\" \
, $fifo= \
" \
, import=$fifo=
Jag valde att göra det egentliga räknekommandot väldigt generellt så att det blir lätt att lägga till flera olika räknekommandon om det skulle visa sig behövas. För tillfället nöjer vi oss med ett enkelt kommando som räknar ut skillnaden mellan två olika värden.
Kod: Markera allt
system.method.insert = \
diff \
, const_simple \
, " arithmetic = \
\"$ cat = \
$argument.0= \
, - \
, $argument.1= \
\" \
"
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:56
av Konservburk
16. Hålla reda på hur länge varje torrent seedats
Att ta reda på hur länge en torrent faktiskt har seedat är ett delikat problem, speciellt om datorn inte är igång dygnet runt. Nu ska vi försöka göra saken betydligt enklare genom att registrera den verkliga seed-tiden. Jag väljer att använda kommandona
d.set_custom5 och
d.get_custom5 för att hålla reda på värdet som måste uppdateras varje gång torrenten stoppas eller startas. För att göra det hela någorlunda hanterbart så skapar vi ett kommando som har hand om den saken.
Kod: Markera allt
system.method.insert = \
d.register_seed_time \
, const_simple \
, " branch = \
d.get_custom5= \
, \" \
d.set_custom5 = \
\\\"$ \
cat = \
\\\\\\\"$ \
return = \
\\\\\\\\\\\\\\\"$ \
diff = \
$system.time= \
, $d.get_custom5= \
\\\\\\\\\\\\\\\" \
\\\\\\\" \
\\\" \
\" \
, d.is_active= \
, d.set_custom5=$cat=$system.time= \
" \
, " require = \
$d.get_custom5= \
, $argument.0= \
, \
, \"$ cat = \
d.set_custom5= \
, $argument.0= \
\" \
" \
, " d.completed = \
, d.set_custom5= \
"
Det kanske inte är helt uppenbart varför
d.register_seed_time-kommandot ser ut som det gör. Logiken bakom är hur som helst att seed-tiden uppdateras om den redan finns registrerad, i annat fall nollställs den. Sedan görs en kontroll med vårt egna
require-kommando så att seed-tiden verkligen uppdaterades åt rätt håll, annars återställs det tidigare värdet. Kontrollen behövs för de fall när
rtorrent inte avslutats korrekt så att seed-tiden aldrig uppdaterades när torrenten stängdes. Slutligen görs en kontroll så att torrenten verkligen är klar, i annat fall avregistreras seed-tiden helt. Nu behöver vi bara koppla kommandot till några lämpliga händelser.
Kod: Markera allt
schedule = monitor_seed_time , 60 , 60 \
, " d.multicall = incomplete , d.register_seed_time=$d.get_custom5= "
Kod: Markera allt
system.method.set_key = event.download.finished , initialize_seed_time \
, d.register_seed_time=$system.time=
Kod: Markera allt
system.method.set_key = event.download.paused , save_seed_time \
, d.register_seed_time=
Kod: Markera allt
system.method.set_key = event.download.resumed , restore_seed_time \
, d.register_seed_time=$d.get_custom5=
Jag väljer att köra en uppdatering i minuten, samt en när torrenten startas och en när den stoppas. Dessutom nollställs seed-tiden precis när en torrenten faktiskt blir klar.
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:57
av Konservburk
17. Ytterligare en faktiskt användning av det vi hittills gjort
Det är åter igen dags att få till något mer direkt användbart. Men först behöver vi ett kommando som plockar fram seed-tiden vi redan har registrerat. Exakt hur vi får fram den avgörs av om torrenten är startad eller stoppad. I övrigt ska det inte vara några konstigeheter alls.
Kod: Markera allt
system.method.insert = \
d.get_seed_time \
, const_simple \
, " branch = \
not=$d.get_custom5= \
, return.set=0 \
, d.is_active= \
, \" \
diff = \
$system.time= \
, $d.get_custom5= \
\" \
, return.set=$d.get_custom5= \
"
Nu får vi tillslut användning för att vi bara hårdkodade
d.completed i det kombinerade testet tidigare. Det betyder att vi nu kan skapa ett nytt kombinerat test väldigt enkelt, men med andra villkor, nämligen en minsta seed-tid och en speciell tracker. Här får vi åter igen användning för vårt
require-kommando.
Kod: Markera allt
system.method.insert = \
on_tracker_and_time \
, const_simple \
, " completed_dual_filter = \
$argument.0= \
, \"$ cat = \
d.match_tracker= \
, $argument.1= \
\" \
, \"$ cat = \
require=$return=$d.get_seed_time= \
, \\\\\\\, \
, $argument.2= \
\" \
"
Slutligen är det bara kvar att koppla det hela till ett
schedule-kommando. Jag väljer som exempel att alla torrents från
thepiratebay.org ska kontrolleras var tionde minut och stoppas om de har seedats i mer än 1 miljon sekunder. Åter igen är backslasharna innan punkten inte nödvändiga, men är där för att visa hur många de faktiskt ska vara.
Kod: Markera allt
schedule = close_on_tracker_and_time , 600 , 600 \
, " on_tracker_and_time = \
started \
, thepiratebay\\\\\\\\\\\\\\\\.org \
, 1000000 \
, d.stop_and_close= \
"
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:57
av Konservburk
rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:57
av Konservburk
19. Efterord
Det här var egentligen tänkt som en julkalender, men jag fick aldrig riktigt tid att avsluta den helt. I de sista delarna skulle jag ha tagit upp lite om hur torrent-grupper fungerar. Vi får se om jag får tid och inspiration att fylla på med den biten senare.
Re: rTorrent: En avancerad djupgående guide till ~/.rtorrent.rc
Postat: 31 dec 2008, 15:57
av Konservburk
Finns det förresten någon som har lite kul ideér om vad man skulle kunna göra i ~/.rtorrent.rc?