<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xml" href="https://jon.eus/feed.xslt.xml"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://jon.eus/feed/tag/frikikeriak.xml" rel="self" type="application/atom+xml" /><link href="https://jon.eus/" rel="alternate" type="text/html" /><updated>2026-04-15T11:27:34+02:00</updated><id>https://jon.eus/feed/tag/frikikeriak.xml</id><title type="html">~jon</title><author><name>Jon</name></author><entry><title type="html">Datu-baseak ziztuan bete INSERT ordez COPY erabiliz</title><link href="https://jon.eus/posts/20210319-postgres-copy" rel="alternate" type="text/html" title="Datu-baseak ziztuan bete INSERT ordez COPY erabiliz" /><published>2021-03-19T00:00:00+01:00</published><updated>2021-03-19T00:00:00+01:00</updated><id>https://jon.eus/posts/postgres-copy</id><content type="html" xml:base="https://jon.eus/posts/20210319-postgres-copy"><![CDATA[<p>Webgune honetako orrialde ezberdinak kuxkuxeatu badituzue, informatika 
ingeniaria naizela irakurriko zenuten, ikasketaz zein ofizioz. Azkenaldian nire 
lanak datu-baseak maneiatzean datza, hala nola datuak sartu, ezabatu, eguneratu, 
eta beste hainbeste.</p>

<p>PostgreSQL <em>database management system</em> (DBMS, euskaraz <em>datu-base 
kudeaketa-sistema</em>) erabiltzen dut. Unibertsitateko ikasketetan zehar MySQL 
(orain MariaDB), Oracle eta SQLite-rekin jardun ondoren, Karrera Amaierako 
Proiektuarekin hastear nenbilenean ezagutu nuen. Zergatik aldaketa? Software 
askea izateaz gain, besteak beste, <a href="https://www.postgresql.org/docs/current/plpgsql.html">PL/pgSQL</a> lengoaia 
prozeduralagatik —Oracle-ren PL/SQL oinarritua—, non zuzenean datu-basearekin prozesu konplexuagoak garatu baitaitezke.<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<p>Horrelako batean, prozesua nahi baino geldoago zihoala-eta —presarekin nenbilen, 
agian gehiegi—, bizkortzeko alternatiben bila hasi nintzen. Eta hara non aurkitu 
nuen <a href="https://www.postgresql.org/docs/current/sql-copy.html"><code class="language-plaintext highlighter-rouge">COPY</code></a>, zeinak zuzenean fitxategi mota batzuk —CSV da ohikoena— 
datu-basera sartzea ahalbidetzen duen. Dokumentazioa irakurri ondoan,
<a href="https://www.postgresql.org/docs/current/app-psql.html"><code class="language-plaintext highlighter-rouge">psql</code></a> zerabilen <em>script</em> bat garatu nuen, konponbide azkar, arin eta 
errazena zelako. Zeharo harrituta geratu nintzen. 40 GB inguru ordu bat baino 
gutxiagotan sartu ziren, adibidez. Hori bata bestearen atzetik egin nuela, 
<a href="https://linux.die.net/man/1/parallel"><code class="language-plaintext highlighter-rouge">parallel</code></a> erabili barik.</p>

<p>Sines nazazuen, hurrengo paragrafoetan Python-en garatutako adibide oso 
batekin erakutsiko dizuet <code class="language-plaintext highlighter-rouge">COPY</code> aginduaren potentzia ohiko 
<a href="https://www.postgresql.org/docs/current/sql-insert.html"><code class="language-plaintext highlighter-rouge">INSERT</code></a> aginduarekin alderaturik. Anitzek darabilten 
<a href="https://www.psycopg.org/docs/usage.html"><code class="language-plaintext highlighter-rouge">psycopg2</code></a> moduluaren laguntzaz.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup></p>

<p>Lehenik eta behin, datu-base sistemaren osotasuna bermatzearren, badaezpada, 
berri bat sortzea hobe. Honetarako, <a href="https://www.postgresql.org/docs/current/app-createdb.html"><code class="language-plaintext highlighter-rouge">createdb</code></a> kontsola-programa 
eskaintzen du PostgreSQL-ek.</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>createdb <span class="nb">test</span> <span class="nt">-e</span>
<span class="gp">SELECT pg_catalog.set_config('search_path', '', false);</span><span class="w">
</span><span class="gp">CREATE DATABASE test;</span><span class="w">
</span></code></pre></div></div>

<p>Jakina, datu-basean lan egiteko konektatzea premiazkoa da, bide batez 
<code class="language-plaintext highlighter-rouge">psycopg2</code>-ek <em>kurtsore</em> deritzona sortuz:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">conn</span> <span class="o">=</span> <span class="n">psycopg2</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span><span class="n">dbname</span><span class="o">=</span><span class="sh">'</span><span class="s">test</span><span class="sh">'</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="sh">'</span><span class="s">postgres</span><span class="sh">'</span><span class="p">)</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="nf">cursor</span><span class="p">()</span>
</code></pre></div></div>

<p>Datuak non edo non kokatu behar dira. Horretarako hiru zutabedun <code class="language-plaintext highlighter-rouge">numbers</code> 
izeneko taula sortuko da:</p>

<table>
  <thead>
    <tr>
      <th><strong>Zutabea</strong></th>
      <th><strong>Esanahia</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">number</code></td>
      <td>Zenbakia bera (hau da, <em>1</em>).</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">cardinal</code></td>
      <td>Kardinala (<em>bat</em>).</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ordinal</code></td>
      <td>Ordinala (<em>lehen</em>).</td>
    </tr>
  </tbody>
</table>

<p>Betiere —usadioz, esperientziagatik— <code class="language-plaintext highlighter-rouge">IF NOT EXISTS</code> jarriz, nahiz testuinguru 
honetan hautazkoa izan:<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup></p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">IF</span> <span class="k">NOT</span> <span class="k">EXISTS</span> <span class="n">numbers</span> <span class="p">(</span>
    <span class="n">number</span> <span class="nb">integer</span><span class="p">,</span>
    <span class="n">cardinal</span> <span class="nb">text</span><span class="p">,</span>
    <span class="n">ordinal</span> <span class="nb">text</span>
<span class="p">);</span>
</code></pre></div></div>

<p>Python-en itxura hau izango duelarik:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">create_numbers_table</span> <span class="o">=</span> \
<span class="sh">"""</span><span class="s">
CREATE TABLE IF NOT EXISTS numbers (
    number integer,
    cardinal text,
    ordinal text
);
</span><span class="sh">"""</span>
<span class="n">cur</span><span class="p">.</span><span class="nf">execute</span><span class="p">(</span><span class="n">create_numbers_table</span><span class="p">)</span>
</code></pre></div></div>

<p>Ondo, taula sortu da. Hutsik, noski. Orain, <a href="https://pypi.org/project/inflect/"><code class="language-plaintext highlighter-rouge">inflect</code></a> moduluaren 
laguntzarekin, zerotik hasita milioi bat zenbakiren informazio hori idatziko da 
CSV fitxategi batean —ingelesez—, hurrengo kodearekin:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">csv_filename</span> <span class="o">=</span> <span class="sh">'</span><span class="s">numbers.csv</span><span class="sh">'</span>
<span class="n">columns</span> <span class="o">=</span> <span class="p">[</span><span class="sh">"</span><span class="s">number</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">cardinal</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">ordinal</span><span class="sh">"</span><span class="p">]</span>

<span class="n">p</span> <span class="o">=</span> <span class="n">inflect</span><span class="p">.</span><span class="nf">engine</span><span class="p">()</span>
<span class="k">with</span> <span class="nf">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">,</span> <span class="sh">'</span><span class="s">w</span><span class="sh">'</span><span class="p">,</span> <span class="n">newline</span><span class="o">=</span><span class="sh">''</span><span class="p">)</span> <span class="k">as</span> <span class="n">csvfile</span><span class="p">:</span>
    <span class="n">num_writer</span> <span class="o">=</span> <span class="n">csv</span><span class="p">.</span><span class="nf">writer</span><span class="p">(</span><span class="n">csvfile</span><span class="p">)</span>
    <span class="n">num_writer</span><span class="p">.</span><span class="nf">writerow</span><span class="p">(</span><span class="n">columns</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1000000</span><span class="p">):</span>
        <span class="n">num_writer</span><span class="p">.</span><span class="nf">writerow</span><span class="p">([</span><span class="n">i</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="nf">number_to_words</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="n">p</span><span class="p">.</span><span class="nf">number_to_words</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="nf">ordinal</span><span class="p">(</span><span class="n">i</span><span class="p">))])</span>
</code></pre></div></div>

<p>Fitxategi luzeegia da blog-posta batean txertatzeko, beraz lehen 5 lerroekin 
ideia bat egin dezakezue.</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span><span class="nb">head</span> <span class="nt">-5</span> numbers.csv | csview
<span class="go">+--------+----------+---------+
| number | cardinal | ordinal |
+--------+----------+---------+
| 0      | zero     | zeroth  |
| 1      | one      | first   |
| 2      | two      | second  |
| 3      | three    | third   |
+--------+----------+---------+
</span></code></pre></div></div>

<p>Esan bezala, taula bi modutan beteko da:</p>

<ol>
  <li>
    <p><strong>Fitxategi osoa batera, <code class="language-plaintext highlighter-rouge">COPY</code> erabiliz:</strong></p>

    <p>Komando honen sintaxia nahiko erraza da (ikus esteka). Sarrera estandarretik irakurri nahi denez, <code class="language-plaintext highlighter-rouge">numbers.csv</code> ordez <code class="language-plaintext highlighter-rouge">STDIN</code> 
 jarriko da. Datu-basearekin bitartekari baten laguntzaz gaudelako hizketan, 
 zer edo zelan esatearren.</p>

    <p>Ohartxo bat, badaezpada ere: fitxategia <a href="https://www.gnu.org/software/gzip/manual/gzip.html"><code class="language-plaintext highlighter-rouge">gzip</code></a>-ekin konprimituta 
 balego, lehenik deskonprimitu egin beharko litzateke eskura ditugun tresnekin. 
 Adibide batzuk: Pythonen, <a href="https://docs.python.org/3/library/gzip.html">izen bereko modulua</a> dago; POSIX-en, 
 <a href="https://linux.die.net/man/1/zcat"><code class="language-plaintext highlighter-rouge">zcat</code></a>; Javan, <code class="language-plaintext highlighter-rouge">GZIPInputStream</code> klasea, etab.</p>

    <p>Guzti hau kontuan hartuta, honela geratuko litzateke:</p>

    <div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">COPY</span> <span class="n">numbers</span> <span class="k">FROM</span> <span class="k">STDIN</span> <span class="n">CSV</span> <span class="n">HEADER</span> <span class="k">DELIMITER</span> <span class="s1">','</span>
</code></pre></div>    </div>

    <p>Zorionez, <code class="language-plaintext highlighter-rouge">psycopg2</code>-ek <a href="https://www.psycopg.org/docs/usage.html#using-copy-to-and-copy-from">funtzionaltasun honen euskarria du</a>. 
 Kakotxak direla-eta <code class="language-plaintext highlighter-rouge">copy_from()</code> <em>kexatu</em> ondoren, <code class="language-plaintext highlighter-rouge">copy_expert()</code> 
 erabiltzea hoberena, berariazko erabilpenak ahaltzen baititu.</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">copy_numbers</span> <span class="o">=</span> <span class="sh">"</span><span class="s">COPY numbers FROM STDIN CSV HEADER DELIMITER </span><span class="sh">'</span><span class="s">,</span><span class="sh">'"</span>
 <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
 <span class="n">cur</span><span class="p">.</span><span class="nf">copy_expert</span><span class="p">(</span><span class="n">copy_numbers</span><span class="p">,</span> <span class="nf">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">))</span>
 <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
 <span class="n">copy_time</span> <span class="o">=</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span>
</code></pre></div>    </div>
  </li>
  <li>
    <p><strong>Lerro bakoitzeko <code class="language-plaintext highlighter-rouge">INSERT</code> bat exekutatuz:</strong></p>

    <p>SQL-ko klasikoak diren <code class="language-plaintext highlighter-rouge">SELECT</code>, <code class="language-plaintext highlighter-rouge">UPDATE</code> eta <code class="language-plaintext highlighter-rouge">DELETE</code>-ren senidea,<sup id="fnref:4"><a href="#fn:4" class="footnote" rel="footnote" role="doc-noteref">4</a></sup> 
 zeinak errenkada bat taula batean eransten duen. Segurtasuna bermatzearren, 
 nahiz eta <code class="language-plaintext highlighter-rouge">localhost</code>-en premiazkoa ez izan, <em>SQL injection</em> lako 
 ahultasunak saihesteko <a href="https://www.postgresql.org/docs/current/sql-prepare.html"><em>prepared statement</em></a> deritzona erabiliko 
 da, gisa honetan:</p>

    <div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">INSERT</span> <span class="k">INTO</span> <span class="n">numbers</span> <span class="p">(</span><span class="n">number</span><span class="p">,</span> <span class="n">cardinal</span><span class="p">,</span> <span class="n">ordinal</span><span class="p">)</span> <span class="k">VALUES</span> <span class="p">(</span><span class="o">%</span><span class="n">s</span><span class="p">,</span> <span class="o">%</span><span class="n">s</span><span class="p">,</span> <span class="o">%</span><span class="n">s</span><span class="p">)</span>
</code></pre></div>    </div>

    <p>Exekutatu baino lehen adierazpena prestatuko da. <code class="language-plaintext highlighter-rouge">%s</code> horiek, hurrenez 
 hurren, CSV-ko eduki baliokieekin ordezkatuko dira datuak gehitzerakoan; 
 zutabeeen moten arabera egiaztapenak eginez. Nire gomendioa hauek 
 erabiltzearen ohitura hartzea da, zeren jende-modu maltzurrek argitaratutako 
 zerbitzuetan datuak lapurtu edo ezabatzeko aukera ez baitute alferrik 
 galduko. Denbora joan ahala, erreflexu bilakatuko da.</p>

    <p>Ahalik eta lasterren exekutatu dadin, sortu berri den <code class="language-plaintext highlighter-rouge">numbers.csv</code> 
 fitxategia irakurriko da lerroz lerro. Goiburua taularen zutabe-izenen 
 zerrenda denez, <a href="https://docs.python.org/3/library/csv.html#csv.DictReader"><code class="language-plaintext highlighter-rouge">DictReader</code></a> erabil dezakegu guztia 
 errazteko:</p>

    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">insert_number</span> <span class="o">=</span> <span class="sh">"</span><span class="s">INSERT INTO numbers (number, cardinal, ordinal) VALUES (%s, %s, %s)</span><span class="sh">"</span>
 <span class="k">with</span> <span class="nf">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">,</span> <span class="sh">'</span><span class="s">r</span><span class="sh">'</span><span class="p">,</span> <span class="n">newline</span><span class="o">=</span><span class="sh">''</span><span class="p">)</span> <span class="k">as</span> <span class="n">csvfile</span><span class="p">:</span>
     <span class="n">num_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="p">.</span><span class="nc">DictReader</span><span class="p">(</span><span class="n">csvfile</span><span class="p">)</span>
     <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
     <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">num_reader</span><span class="p">:</span>
         <span class="n">cur</span><span class="p">.</span><span class="nf">execute</span><span class="p">(</span><span class="n">insert_number</span><span class="p">,</span> <span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="sh">'</span><span class="s">number</span><span class="sh">'</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="sh">'</span><span class="s">cardinal</span><span class="sh">'</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="sh">'</span><span class="s">ordinal</span><span class="sh">'</span><span class="p">]))</span>
     <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
 <span class="n">insert_time</span> <span class="o">=</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span>
</code></pre></div>    </div>
  </li>
</ol>

<p>Konturatuko zineten iraupenak <code class="language-plaintext highlighter-rouge">copy_time</code> eta <code class="language-plaintext highlighter-rouge">insert_time</code> aldagaien bidez 
kalkulatu direla, hurrenez hurren. Informazio hau kontsolan forma estetiko 
batean erakusteko, <a href="https://pypi.org/project/tabulate/"><code class="language-plaintext highlighter-rouge">tabulate</code></a> erabiliko da:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">table</span> <span class="o">=</span> <span class="p">[[</span><span class="sh">"</span><span class="s">COPY</span><span class="sh">"</span><span class="p">,</span><span class="n">copy_time</span><span class="p">],[</span><span class="sh">"</span><span class="s">INSERT</span><span class="sh">"</span><span class="p">,</span><span class="n">insert_time</span><span class="p">]]</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="sh">"</span><span class="s">Statement</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">t (s)</span><span class="sh">"</span><span class="p">]</span>
<span class="nf">print</span><span class="p">(</span><span class="nf">tabulate</span><span class="p">(</span><span class="n">table</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">floatfmt</span><span class="o">=</span><span class="sh">"</span><span class="s">.2f</span><span class="sh">"</span><span class="p">))</span>
</code></pre></div></div>

<p>Kode osoa hemen ikusgai.
</p>
<details>
  <summary>
    <p><code class="language-plaintext highlighter-rouge">pgsql_copy_vs_insert.py</code></p>
  </summary>

  <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="n">csv</span>
<span class="kn">import</span> <span class="n">time</span>
<span class="kn">import</span> <span class="n">inflect</span>
<span class="kn">import</span> <span class="n">psycopg2</span>
<span class="kn">from</span> <span class="n">tabulate</span> <span class="kn">import</span> <span class="n">tabulate</span>

<span class="n">csv_filename</span> <span class="o">=</span> <span class="sh">'</span><span class="s">numbers.csv</span><span class="sh">'</span>
<span class="n">columns</span> <span class="o">=</span> <span class="p">[</span><span class="sh">"</span><span class="s">number</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">cardinal</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">ordinal</span><span class="sh">"</span><span class="p">]</span>
<span class="n">create_numbers_table</span> <span class="o">=</span> \
<span class="sh">"""</span><span class="s">
CREATE TABLE IF NOT EXISTS test.numbers (
    number integer,
    cardinal text,
    ordinal text
);
</span><span class="sh">"""</span>
<span class="n">copy_numbers</span> <span class="o">=</span> \
<span class="sh">"""</span><span class="s">
COPY test.numbers from STDIN CSV HEADER DELIMITER </span><span class="sh">'</span><span class="s">,</span><span class="sh">'</span><span class="s"> NULL AS </span><span class="sh">'</span><span class="s">null</span><span class="sh">'</span><span class="s">
</span><span class="sh">"""</span>
<span class="n">insert_number</span> <span class="o">=</span> \
<span class="sh">"""</span><span class="s">
INSERT INTO test.numbers (number, cardinal, ordinal) VALUES (%s, %s, %s)
</span><span class="sh">"""</span>

<span class="k">try</span><span class="p">:</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">inflect</span><span class="p">.</span><span class="nf">engine</span><span class="p">()</span>

    <span class="n">conn</span> <span class="o">=</span> <span class="n">psycopg2</span><span class="p">.</span><span class="nf">connect</span><span class="p">(</span><span class="n">dbname</span><span class="o">=</span><span class="sh">'</span><span class="s">test</span><span class="sh">'</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="sh">'</span><span class="s">postgres</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">cur</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="nf">cursor</span><span class="p">()</span>

    <span class="n">cur</span><span class="p">.</span><span class="nf">execute</span><span class="p">(</span><span class="n">create_numbers_table</span><span class="p">)</span>

    <span class="k">with</span> <span class="nf">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">,</span> <span class="sh">'</span><span class="s">w</span><span class="sh">'</span><span class="p">,</span> <span class="n">newline</span><span class="o">=</span><span class="sh">''</span><span class="p">)</span> <span class="k">as</span> <span class="n">csvfile</span><span class="p">:</span>
        <span class="n">num_writer</span> <span class="o">=</span> <span class="n">csv</span><span class="p">.</span><span class="nf">writer</span><span class="p">(</span><span class="n">csvfile</span><span class="p">)</span>
        <span class="n">num_writer</span><span class="p">.</span><span class="nf">writerow</span><span class="p">(</span><span class="n">columns</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range </span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1000000</span><span class="p">):</span>
            <span class="n">num_writer</span><span class="p">.</span><span class="nf">writerow</span><span class="p">([</span><span class="n">i</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="nf">number_to_words</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="n">p</span><span class="p">.</span><span class="nf">number_to_words</span><span class="p">(</span><span class="n">p</span><span class="p">.</span><span class="nf">ordinal</span><span class="p">(</span><span class="n">i</span><span class="p">))])</span>

    <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
    <span class="n">cur</span><span class="p">.</span><span class="nf">copy_expert</span><span class="p">(</span><span class="n">copy_numbers</span><span class="p">,</span> <span class="nf">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">))</span>
    <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
    <span class="n">copy_time</span> <span class="o">=</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span>

    <span class="k">with</span> <span class="nf">open</span><span class="p">(</span><span class="n">csv_filename</span><span class="p">,</span> <span class="sh">'</span><span class="s">r</span><span class="sh">'</span><span class="p">,</span> <span class="n">newline</span><span class="o">=</span><span class="sh">''</span><span class="p">)</span> <span class="k">as</span> <span class="n">csvfile</span><span class="p">:</span>
        <span class="n">num_reader</span> <span class="o">=</span> <span class="n">csv</span><span class="p">.</span><span class="nc">DictReader</span><span class="p">(</span><span class="n">csvfile</span><span class="p">)</span>
        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">num_reader</span><span class="p">:</span>
            <span class="n">cur</span><span class="p">.</span><span class="nf">execute</span><span class="p">(</span><span class="n">insert_number</span><span class="p">,</span> <span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="sh">'</span><span class="s">number</span><span class="sh">'</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="sh">'</span><span class="s">cardinal</span><span class="sh">'</span><span class="p">],</span> <span class="n">row</span><span class="p">[</span><span class="sh">'</span><span class="s">ordinal</span><span class="sh">'</span><span class="p">]))</span>
        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="nf">perf_counter</span><span class="p">()</span>
    <span class="n">insert_time</span> <span class="o">=</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span>

    <span class="n">table</span> <span class="o">=</span> <span class="p">[[</span><span class="sh">"</span><span class="s">COPY</span><span class="sh">"</span><span class="p">,</span><span class="n">copy_time</span><span class="p">],[</span><span class="sh">"</span><span class="s">INSERT</span><span class="sh">"</span><span class="p">,</span><span class="n">insert_time</span><span class="p">]]</span>
    <span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="sh">"</span><span class="s">Statement</span><span class="sh">"</span><span class="p">,</span> <span class="sh">"</span><span class="s">t (s)</span><span class="sh">"</span><span class="p">]</span>

    <span class="nf">print</span><span class="p">(</span><span class="nf">tabulate</span><span class="p">(</span><span class="n">table</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">floatfmt</span><span class="o">=</span><span class="sh">"</span><span class="s">.2f</span><span class="sh">"</span><span class="p">))</span>

<span class="nf">except </span><span class="p">(</span><span class="nb">Exception</span><span class="p">,</span> <span class="n">psycopg2</span><span class="p">.</span><span class="n">DatabaseError</span><span class="p">)</span> <span class="k">as</span> <span class="n">error</span><span class="p">:</span>
    <span class="nf">print</span><span class="p">(</span><span class="n">error</span><span class="p">)</span>

<span class="k">finally</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">conn</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
        <span class="n">conn</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
</code></pre></div>  </div>
</details>

<p>Nire saiakeren arabera, gutxienez 25 bider azkarragoa da lehena bigarrena baino. 
Esate baterako:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>python pgsql_copy_vs_insert.py
<span class="go">Statement      t (s)
-----------  -------
COPY            1.65
INSERT         46.01
</span></code></pre></div></div>

<p>Iraupen hauekin, eta mila bider datu gehiagorekin <code class="language-plaintext highlighter-rouge">COPY</code>-k, alde batetik, ordu 
erdi inguru iraungo luke eta <code class="language-plaintext highlighter-rouge">INSERT</code>-ek, bestalde, hamabi. <code class="language-plaintext highlighter-rouge">parallel</code> gabe, 
jakina. Benetan aintzat hartzeko gauza, ez da hala?</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">

      <p>Gauza konplexuagoak egin nahi izanez gero, Python ere erabil daiteke, bide 
batez: <a href="https://www.postgresql.org/docs/current/plpython.html">PL/Python</a> du izena. PL/pgSQL-en ezinezkoak edo motelak 
diren konputazioak egiteko oso ongi dator. Edozelan ere, C-n edo C++-n 
hedapenak gara daitezke. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:2">

      <p>Egiari zor, lanean darabildan Java-n garatu nuen lehenik, 
<a href="https://jdbc.postgresql.org/documentation/publicapi/org/postgresql/copy/CopyManager.html"><code class="language-plaintext highlighter-rouge">CopyManager</code></a> erabiliz, besteak beste. Alde batetik, ez du 
fama onik, ez (hain) handirik Python-en aldean; bestetik, JDBC (<em>Java 
Database Connectivity</em>) interfazea azaltzeak ez du merezi. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:3">

      <p><a href="https://www.python.org/dev/peps/pep-0249/#commit">PEP 249</a> errespetatuz, <code class="language-plaintext highlighter-rouge">autocommit</code> modua beti dago itzalita —hau 
da, datuak ez dira gordeko—; garatzaileak piztu behar du eta <code class="language-plaintext highlighter-rouge">commit()</code> 
erabili datuak gorde daitezen. Hala denean, <em>script</em> hau behin eta berriz 
exekutatzean taula lehen aldian bakarrik sortuko da. Kontuan izan, baita 
ere, <a href="https://www.postgresql.org/docs/current/sql-truncate.html"><code class="language-plaintext highlighter-rouge">TRUNCATE</code></a> erabili ezean etengabe handituko dela. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:4">

      <p>Datu-baseetako <a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete#Database_applications">CRUD</a> (<em>Create, Read, Update, Delete</em>) oinarrizko 
operazioak. Hurrenez hurren, <code class="language-plaintext highlighter-rouge">INSERT</code>, <code class="language-plaintext highlighter-rouge">SELECT</code>, <code class="language-plaintext highlighter-rouge">UPDATE</code> eta <code class="language-plaintext highlighter-rouge">DELETE</code>. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><category term="frikikeriak" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">HTTPS Apache-n Certbot bidez</title><link href="https://jon.eus/posts/20200721-https-certbot-apache" rel="alternate" type="text/html" title="HTTPS Apache-n Certbot bidez" /><published>2020-07-21T00:00:00+02:00</published><updated>2020-07-21T00:00:00+02:00</updated><id>https://jon.eus/posts/https-certbot-apache</id><content type="html" xml:base="https://jon.eus/posts/20200721-https-certbot-apache"><![CDATA[<p><a href="/posts/20180108-ssl-doan-eff-i-esker">Aspaldi idatzi nuen</a> honi buruz, baina
eguneraketa bat behar zuen.</p>

<p>Kudeatzen ditudan zerbitzu batzuk HTTPS euskarri gabe erabili izan ditut
gutxi arte. Dirudienez, Chrome-k HTTP deskargak blokeatu egingo ditu
segurtasun arazoengatik. Honetarako, TLS ziurtagiriak instalatu behar
nituen. Besteren faltan, <a href="https://eff.org">EFF</a>-k
<a href="https://certbot.eff.org">certbot</a> bidez eskainitako doako <a href="https://letsencrypt.org">Let’s
Encrypt</a> ziurtagiriak jarri nizkien.</p>

<p>Zerbitzaren sistema eragilea Debian da, eta Apache erabiltzen du web
orriak zerbitzatzeko. Nginx ere erabiltzen dut. Dena den, prozesu
agnostikoa azalduko dut.</p>

<h2 id="certbot-en-instalazioa">Certbot-en instalazioa</h2>

<p>Lehenik eta behin, Certbot instalatuko dugu:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>wget https://dl.eff.org/certbot-auto
<span class="gp">$</span><span class="w"> </span><span class="nb">mv </span>certbot-auto /usr/local/bin/
<span class="gp">$</span><span class="w"> </span><span class="nb">chown </span>root /usr/local/bin/certbot-auto
<span class="gp">$</span><span class="w"> </span><span class="nb">chmod </span>0755 /usr/local/bin/certbot-auto
</code></pre></div></div>

<h2 id="ziurtagirien-instalazioa">Ziurtagirien instalazioa</h2>

<p>Hemen, bi alternatiba ditugu: <code class="language-plaintext highlighter-rouge">apache</code> plugina alde batetik, eta <code class="language-plaintext highlighter-rouge">webroot</code> bestetik.</p>

<h3 id="automatikoa-plugin-bidez">Automatikoa (plugin bidez)</h3>

<p>Prozesua nahiko sinplea da, kontsolan hurrengoa exekutatuz:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>certbot-auto certonly <span class="nt">--apache</span>
</code></pre></div></div>

<p>Hemen <em>prompt</em> interaktibo bat azalduko da, hobespenak eskatuz: aukeratutako domeinu eta azpidomeinuak, zerbitzatzeko modua (HTTP zuzena
ala ez), zure eposta, etab. Alde batetik, zertifikatua sortuko du eta bestetik, konfigurazio fitxategietan SSL-ri dagozkionak erantsiko dira. Beraz, orain apache2 berrabiaraztea falta da:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>service apache2 restart <span class="c"># Debian, adibidez</span>
<span class="gp">$</span><span class="w"> </span>service httpd restart <span class="c"># Arch, adibidez</span>
</code></pre></div></div>

<p>(nginx erabiltzen baduzu, <a href="/posts/20180108-ssl-doan-eff-i-esker">prozesu berbera</a> da <code class="language-plaintext highlighter-rouge">apache</code> ordez <code class="language-plaintext highlighter-rouge">nginx</code> erabilita.)</p>

<h3 id="eskuz-webroot-bidez">Eskuz (webroot bidez)</h3>

<p>Nire kasuan, aurreko plugin-arekin arazoak izan nituen, TLS-ren
<em>challenge</em>-ak gaindiezinak zirelako. Certbot-ek berak azaltzen du nola
konpondu, eta webroot (web erro) bat erabiltzea gomendatzen du. Hau
luzeago egiten da, banaka joan behar delako. Bestalde, eskuz egiteak
Apache-ren konfigurazioa ikasten lagundu dit.</p>

<p>Hurrengo komandoa erabili behar da:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>certbot-auto certonly <span class="nt">--webroot</span> <span class="nt">-w</span> &lt;kokapena&gt; <span class="nt">-d</span> &lt;domeinua&gt;
</code></pre></div></div>

<p>Kasu honetan, fitxategia eskuz aldatu beharko duzu, honelako
zerbait ezarriz:</p>

<div class="language-apache highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">&lt;</span><span class="nl">VirtualHost</span><span class="sr"> *:80</span><span class="p">&gt;
</span>    <span class="nc">ServerName</span> &lt;domeinua&gt;
    <span class="nc">RedirectMatch</span> <span class="ss">permanent</span> ^(.*)$ https://&lt;domeinua&gt;$1
<span class="p">&lt;/</span><span class="nl">VirtualHost</span><span class="p">&gt;
</span>
<span class="p">&lt;</span><span class="nl">VirtualHost</span><span class="sr"> _default_:443</span><span class="p">&gt;
</span>    <span class="nc">ServerName</span> &lt;domeinua&gt;
    <span class="nc">DocumentRoot</span> &lt;kokapena&gt;
    <span class="nc">SSLEngine</span> <span class="ss">on</span>
    <span class="nc">SSLCertificateFile</span> /etc/letsencrypt/live/&lt;domeinua&gt;/fullchain.pem
    <span class="nc">SSLCertificateKeyFile</span> /etc/letsencrypt/live/&lt;domeinua&gt;/privkey.pem
    <span class="nc">SSLCertificateChainFile</span> /etc/letsencrypt/live/&lt;domeinua&gt;/chain.pem
    <span class="err">[...]</span>
<span class="p">&lt;/</span><span class="nl">VirtualHost</span><span class="p">&gt;
</span></code></pre></div></div>

<p>Konprobatu lehenik eta behin ea guztia ondo dagoen:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>apachectl configtest <span class="c"># Debian, adib.</span>
<span class="gp">$</span><span class="w"> </span>httpd <span class="nt">-t</span> <span class="c"># Arch, adib.</span>
</code></pre></div></div>

<p>Erantzuna <code class="language-plaintext highlighter-rouge">Syntax OK</code> bada, Apache berrabiaraztea falta da:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>service apache2 restart <span class="c"># Debian, adibidez</span>
<span class="gp">$</span><span class="w"> </span>service httpd restart <span class="c"># Arch, adibidez</span>
</code></pre></div></div>

<p>Bejondeizula, orain zure web orrialdeetara HTTPS bidez sar zaitezke!<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<h2 id="ziurtagirien-berritzea">Ziurtagirien berritzea</h2>

<p>Hau ez da guztia. Irakurri dudanaren arabera, ziurtagiri hauek hiru hilabetero iraungitzen dira, beraz aldizka eguneratu behar dira. Horretarako <code class="language-plaintext highlighter-rouge">cron</code> lan bat ezarriko dugu:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>crontab <span class="nt">-e</span>
</code></pre></div></div>

<p>Eta fitxategi honetako amaieran zera jarriko dugu:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>30 2 <span class="k">*</span> <span class="k">*</span> 1 /usr/local/bin/certbot-auto renew <span class="nt">-q</span>
</code></pre></div></div>
<p>Orain ez zara zure ziurtagirien egoeraz kezkatu behar.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">

      <p><a href="https://ssllabs.com">SSL labs</a>-en arabera ziurtagiriaren kalitatea oso ona 
da: B bat. Hori hobetzeko gomendatzen diren neurriak hartu beharko. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:2">

      <p>Beno, aholku gisa hobe proiektuaren egoera jarraitu. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">RSStentzia sare sozialen nagusitasunaren aurrean</title><link href="https://jon.eus/posts/20200624-rsstentzia" rel="alternate" type="text/html" title="RSStentzia sare sozialen nagusitasunaren aurrean" /><published>2020-06-24T00:00:00+02:00</published><updated>2020-06-24T00:00:00+02:00</updated><id>https://jon.eus/posts/rsstentzia</id><content type="html" xml:base="https://jon.eus/posts/20200624-rsstentzia"><![CDATA[<p>Hogeita hamar urte soilik edukirik ere, esango nuke nire bizitzaren erdia baino zertxobait gehiago igaro dudala Interneten, 3. milurteko hasierako 56 kbps modem-etatik hasi eta gaurko zuntz optikoetara arte.<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<p>Kaixo.net, MSN Messenger, Terra-ko txat, IRC, PhpBB bezalako foroetan ha{s|z}i ostean, Web 2.0-aren sorreraren lekuko izan nintzen —ez literalki, egiaz— 2007 inguruan, batxilergoan nengoenean. Aldaketa nabaria izan zen. Alde batetik,  Menéame / Zabaldu / digg / reddit, Marrapuntu / Barrapunto / Slashdot bezalako webgune sozialak gauzatu ziren. Bestetik, blogak modan jarri ziren, eta horiekin batera web jarioak eta sindikazioa.</p>

<p>Etenaldi bat <em>web sindikazioa</em> azaltzeko: laburbilduz, eta nire hitzetan —<a href="https://izaroblog.com/2020/01/27/erabili-itzazu-rss-ak/">Izarok bere blogean azalpen zehatzagoa du</a><sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>— web jarioak formatu estandar bat dira, webgune bateko edukiak harpidetza bezala besteentzat eskugarri jartzeko helburua duena.  Jarioak RSS, JSON eta Atom formatuan aurki daitezke. Azkena da hemen erabiltzen dena.</p>

<p>Hasieran, Google Reader zen askok, tamalez, erabiltzen genuen bezeroa. Estandarra bilakatu zen, eta Google-k zerbitzua itxi zuenean, web jarioek kolpe handia jasan zuten. Alternatiba falta nabaritzen zen: Feedly bezalako alternatibek ez dute hutsune hori betetzea lortu eta nabaria da gainbehera <em>mainstream</em>ean bederen.</p>

<p>Denboraren makinan orainaldira bueltatzeko garaia da. Sare sozialen garaira, alegia. Duela gutxi <a href="https://news.ycombinator.com/item?id=23576022">Reuters-ek bere RSS-ak akabatu dituela</a> irakurri dut Hacker News-en. Arrazoia argi dago. Azkenean, erabileraren ondorioz, ez Reuters-ek bakarrik, idatzizko eduki sortzaile gehienek edukiak Twitter, Facebook, Instagram, TikTok…<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup> auskalo zein bidez partekatzen dituzte, aurretiaz automatizatu ondoren. Gehiagok irakurriko dute. Reuters-en kasuak web jarioena beraientzat gehigarri bat zela nabaritzen du. Etekin ekonimikorik ez badu, denok dakigu istorioa nola bukatzen den.</p>

<p>Egiari zor, ni ere tranpa horretan erori nintzen: Twitter-en albiste zerrendak nituen, eta oraindik Mastodonen ere zerbaitekin aurkitzen naiz. Zorionez, duela zertxobait argia ikusi nuen: zerbitzari honetan ostatatutako Tiny Tiny RSS eta kontsolako <a href="https://newsboat.org/"><code class="language-plaintext highlighter-rouge">newsboat</code></a> testu-bezeroa erabiltzen ditut web jarioak irakurtzeko. GAFAM-etik at.</p>

<p>Hamarkada bat eta paradigma zeharo aldatu da: plataforma pribatuak diren bitartekariak ditugu orain. Batek daki noiz desagertuko diren ekosistema (berriz) suntsituz.</p>

<p>Akatu mezularia eta harpidetu zuzenean: batu zaitez <em>RSStentzia</em>ra.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">

      <p>Esan beharra dut, Euskal Herriarekin alderatuta, Alemaniako interneterako 
sarbidea tamalgarria dela. Nire kontratuaren arabera 50 MB-ko DSL darabilt 
eta ez da guztia heltzen… <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:2">

      <p>Osoki eskertzen dudan <em>Agit-prop</em> edo proselitismo kutsu handiarekin 
idatzia. Hori du helburua azken finean. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:3">

      <p>Azken honen erabiltzaile kopurua harrigarria iruditzen zait, batez ere 
gazteen artean. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><category term="frikikeriak" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Egoera kaotikoari aurre egiteko bideo batzuk</title><link href="https://jon.eus/posts/20200324-36c3" rel="alternate" type="text/html" title="Egoera kaotikoari aurre egiteko bideo batzuk" /><published>2020-03-24T00:00:00+01:00</published><updated>2020-03-24T00:00:00+01:00</updated><id>https://jon.eus/posts/36c3</id><content type="html" xml:base="https://jon.eus/posts/20200324-36c3"><![CDATA[<p>Iazko urtarrilean <a href="https://www.ccc.de/">Chaos Computer Club</a>-aren 35. <em>Chaos Comunication Congress</em>-i buruz <a href="/posts/20190113-35c3">ohartxo bat</a> idatzi nuen. Orain bertsio berri eta berezi batekin nator, koronabirusaren afera dela eta guztiok denbora libre gehiago baitugu.</p>

<p>Aurrekoan esan bezala, hitzaldi gehienak alemanez edo ingelesez egiten dira: Leipzigen (Saxonia, Alemania) ospatzen da. Haatik, bideo batzuk hizkuntza ezberdinetan entzungai daudela dirudi. Besteetarako, azpitituluak egon daitezke eskuragarri. Agian euskaratzera animatzen naiz, baina ez dut ezer promesten. Podcast formatua nahiago baduzue, alternatiba bezala audio formatuan daude eskugarri.</p>

<p>Edizio horretan CCC-ek <em>Exhausting resources</em> azpitutuluarekin klima aldaketa nabarmendu nahi izan du. Horren harira dator lehen iradokizuna: <a href="https://media.ccc.de/v/36c3-10991-science_for_future"><em>Science for future? What we can and need to change to keep climate change low - the scientist view</em></a>.</p>

<p>Osasunari begiratuz, datuak gure onerako nola erabili. Garrantzitsua batez ere bizi dugun osasun krisi larri honetan: <a href="https://media.ccc.de/v/36c3-98-a-hacker-s-guide-to-healthcare-how-to-improve-lives-with-data"><em>A hacker’s guide to healthcare: how to improve lives with data</em></a>.</p>

<p>Aktibismo politiko eta teknologiaren arteko elkarguneari erreparatuz:</p>

<ul>
  <li><a href="https://media.ccc.de/v/36c3-150-the-technical-is-political-tech-s-role-in-oppression-and-what-technicians-can-do-against-it"><em>The technical is political —tech’s role in oppression and what technicians can do against it</em></a>: zapalkuntza, gutxiengoak, Silicon Valley, eta abar.</li>
  <li><a href="https://media.ccc.de/v/36c3-11045-confessions_of_a_future_terrorist"><em>Confessions of a future terrorist: a rough guide to over-regulating free speech with anti-terrorist measures</em></a>: pribatutasun legeei buruz, batik bat.</li>
</ul>

<p>Zientziari buruzko pare bat —hemen nire opilari ikatza, astronomian egiten baitut lan.</p>

<ul>
  <li><a href="https://media.ccc.de/v/36c3-10607-grow_your_own_planet"><em>Grow your own planet: how simulations help us understand the Universe</em></a>: simulazio hidrodinamikoei buruz.</li>
  <li><a href="https://media.ccc.de/v/36c3-oio-201-a-home-among-the-stars-galina-balashova-architect-of-the-soviet-space-programme#t=668"><em>A home among the stars: Galina Balashova, architect of the soviet space programme</em></a>: xelebreki, oraindik sakonean irakurtzeke dudan <a href="https://dom-publishers.com/products/galina-balashova">izen bereko liburua</a> oparitu nion nire buruar 29. urtebetetzean (iaz).</li>
</ul>

<p>Azkenik, teknofiloentzako bitxikeri pare bat. Gurasoak bazarete agian umeekin ere erabil/ikus ditzakezue:</p>

<ul>
  <li><a href="https://media.ccc.de/v/36c3-11195-phyphox_using_smartphone_sensors_for_physics_experiments"><em>phyphox: Using smartphone sensors for physics experiments: an open source project for education, research and tinkering</em></a>: gazteek (eta ez hain gazteek) sentsoreei buruz ikasteko modu interesgarria.</li>
  <li><a href="https://media.ccc.de/v/36c3-10776-hebocon"><em>Hebocon: the sumo robot fight for the technically ungifted</em></a>: hau dibulgazioa baino gehiago aisia da, baina behintzat egun hauetarako jolas interesgarria (eta entretenigarria) izan daiteke.</li>
</ul>

<p>Hauek dira deigarri egiten zaizkidanak. Ez bazaituztet konbentzitu <a href="https://media.ccc.de/c/36c3">webgune ofizialean</a> are gehiago ikusgai. Nik badut plana, beraz. Zuek?</p>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Nire Linux konfigurazioa</title><link href="https://jon.eus/posts/20191128-nire-linux-konfigurazioa" rel="alternate" type="text/html" title="Nire Linux konfigurazioa" /><published>2019-11-28T00:00:00+01:00</published><updated>2019-11-28T00:00:00+01:00</updated><id>https://jon.eus/posts/nire-linux-konfigurazioa</id><content type="html" xml:base="https://jon.eus/posts/20191128-nire-linux-konfigurazioa"><![CDATA[<p><strong>Eguneraketa: 2020-09-28</strong></p>

<p>Edukia ohar batetik orrialde batetara mugitu da, edukia aldakorra delako
eta, batez ere, etorkizunean ohar berbera edo eguneraketak idazteak
merezi ez duelako.</p>

<p><a href="/misc/linux-config">Hemen</a> ikusgai.</p>

<p><strong>Eguneraketa: 2021-03-19</strong></p>

<p>Orrialdearen kokapena aldatu dut, orain <a href="/other/linux">hemen</a> duzue ikusgai.</p>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><category term="frikikeriak" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Softwarearen zoru etikoa</title><link href="https://jon.eus/posts/20191114-softwarearen-zoru-etikoa" rel="alternate" type="text/html" title="Softwarearen zoru etikoa" /><published>2019-11-14T00:00:00+01:00</published><updated>2019-11-14T00:00:00+01:00</updated><id>https://jon.eus/posts/softwarearen-zoru-etikoa</id><content type="html" xml:base="https://jon.eus/posts/20191114-softwarearen-zoru-etikoa"><![CDATA[<p>Agian ohar hau pixkat berandu idazten ari naiz baina buruan izan dut aste
batzuetan zehar.</p>

<p>Dakizuenez, munduan istilu ugari gertatzen ari dira hau irakurtzen ari zareten
bitartean: Ekuador, Txile, Katalunia, Hong Kong, besteak beste. Aipatuko
dudana ez da aurreko zerrendan ageri, ordea. Txinak Uigurrekiko duten
tratamendua. Hizkuntza turkiarra erabiltzen duen etnia hau aspaldian
konzentrazio eremuetan sartzen ari dela dirudi, <a href="https://www.berria.eus/paperekoa/5001884/011/003/2018-08-14/txinak-ukatu-egin-du-milioi-bat-uigur-atxilotuta-dauzkala.htm">ukatzen duten
arren</a>.</p>

<p>Hori dela eta, Notepad++ Windows-eko testu editorearen garatzailek <a href="https://notepad-plus-plus.org/news/v781-free-uyghur-edition/">7.8.1
bertsioari <em>Free Uyghur</em> kode-izena jarri
zioten</a>, urri
bukaeran argitaratua. Erabaki honek txinatar asko ernegatu egin zituen eta
beraien Github-a <a href="https://www.theregister.co.uk/2019/10/31/notepad_china_spam/">kritikaz bete
zuten</a><sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>. Hala
ere, batzuek oraindik <a href="https://github.com/notepad-plus-plus/notepad-plus-plus/issues/7561">jarraitzen
dute</a>
ekinean: <em>Hong Kongeko poliziaren alde nago</em> edo horrelako zerbait dio,
itzultzaile automatiko batzuen arabera.</p>

<p>Nahiz eta gustuko ez izan, Notepad++-en garatzaileek adierazpen politikoak
egiteko askatasun osoa dute. Eta horrelako bidegabekeriak salatzeko bada, are
gehiago. Ez bazaude ados, alternatibak daude.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>.</p>

<p>Aurrekoa oraindik fresko zegoelarik, egun batzuk beranduago, <a href="https://firstdonoharm.dev/">software lizentzia
hipokratikoa</a> aurkitu nuen Pybonacci-ri esker.<sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>
Bereziki interesgarria iduritu zitzaidana honako hau da:</p>

<blockquote>
  <p>Politics and software are so tangled that they cannot be reasonably separated.
Consider the GPS software that tells you how to get to a restaurant; it’s also
used to direct military drones to their targets. The facial recognition
software that unlocks your phone? It’s being used to record, track, and target
the activities of political dissenters. Even simple choices, like limiting
gender options on sign-up forms, have an impact on the well-being of our
users.</p>

  <p>All of these technologies are inherently political. There is no neutral
political position in technology. You can’t build systems that can be
weaponized against marginalized people and take no responsibility for them.</p>
</blockquote>

<p>Interesgarria alde batetik arrazoi guztia duelako: teknologia kapitalismoaren
eskuetan jartzea arazoa oso larria da. Diruak du boterea gaur egungo munduan,
eta horren adibide dira espaziora joateko langileek soldata baxuak izatea
(SpaceX), ibilgailu autonomoek norbait hiltzeari garrantzia kentzea (Uber),
edota informazioa saltzea (Facebook, Google). Bestetik, software librearen
lizentzia batzuek edonori askatasun osoa ematen dielako. Esaterako,
defentsa-enpresek arma, hegazkin, satelite militar eta horrelakoetan <a href="https://www.computerworld.com/article/3442240/the-military-industrial-complex-cannot-get-enough-of-open-source.html">software askea
pozik txertatzen
dute</a>.</p>

<p>Argi dago softwarea politika dela eta horretarako ekimen asko gauzatzen ari
dira. Nola, non, nork, erabili eta abar. Batzuek ez dute gustuko izango, baina
pastela guztiontzat da.</p>

<p>Horregatik existitzen da Fedibertsoa, non norbanakoek kudeatutako alternatiba
independienteek elkarlanean sare federatu bat sortzen dute —izenak
berak esan bezala— enpresek maneiatutako sare sozialen eraginetik at:
Mastodon/Pleroma (Twitter), Pixelfed (Instagram), PeerTube (YouTube), Diaspora
(Facebook), eta beste hainbeste.</p>

<p>Nik oraindik trantsizioa egiteke dut. Momentuz, blog hau eta beste zerbitzu
batzuk ostatatzen dituen zerbitzari honetan <a href="https://git.jon.eus">git</a> zerbitzaria dago erabilgarri; GitHub Microsoftek erosia eta <a href="https://gitlab.com/gitlab-com/www-gitlab-com/issues/5672">Gitlab-ek telemetriarekin
arazoak</a> izan ostean.</p>

<p>Bide luze bat dugu aurretik oraindino.</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">

      <p>Nola esaten da <em>flood</em> euskaraz? Interneteko adiera, ez urarena. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:2">

      <p>Windows ez erabiltzea, adibidez. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:3">

      <p>Python eta bere ekosisteman (zientifikoa, gehienbat) lan ona egiten duen 
garatzaile talde bat. Espainolez, tamalez. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><category term="politika" /><category term="frikikeriak" /><category term="politika" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">35C3</title><link href="https://jon.eus/posts/20190113-35c3" rel="alternate" type="text/html" title="35C3" /><published>2019-01-13T00:00:00+01:00</published><updated>2019-01-13T00:00:00+01:00</updated><id>https://jon.eus/posts/35c3</id><content type="html" xml:base="https://jon.eus/posts/20190113-35c3"><![CDATA[<p>Pasa den 2018 bukaeran <a href="https://www.ccc.de/">Chaos Computer Club</a>-aren <a href="https://events.ccc.de/congress/2018/wiki/index.php/Main_Page">35. Chaos Communication Congress</a>-a ospatu zen Leipzigen. Hackerren eta politikaren arteko elkargunea izan ohi da solasaldien gaia.</p>

<p>Zorionez, grabatu egiten dituzte eta beraien web orrialdean ikus daitezke. Tamalez, alemanez edo ingelesez dira ia guztiak. Audioa eta aurkezpenak ere jeitsi daitezke, MP4 edo WebM formatuan. Hitzaldi interesgarrien zerrenda batekin natorkizue:</p>

<ul>
  <li><a href="https://media.ccc.de/v/35c3-9941-how_facebook_tracks_you_on_android">How Facebook tracks you on Android</a></li>
  <li><a href="https://media.ccc.de/v/35c3-9965-what_is_good_technology">What is good technology?</a></li>
  <li><a href="https://media.ccc.de/v/35c3-9783-the_mars_rover_on-board_computer">The Mars rover on-board computer</a></li>
  <li><a href="https://media.ccc.de/v/35c3-10021-the_precariat_a_disruptive_class_for_disruptive_times">The precariat: a disruptive class for disruptive times</a></li>
  <li><a href="https://media.ccc.de/v/35c3-9451-simulating_universes">Simulating universes</a></li>
  <li><a href="https://media.ccc.de/v/35c3-9462-what_the_fax">What the fax?!</a></li>
</ul>

<p>Oraindik ikusteko ditut. Hamaika hitzaldi interesgarri daude, hau nire gomendio-sorta da. <a href="https://media.ccc.de/c/35c3">Hemen</a> guztiak ikusgai.</p>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">SSL doan EFF-i esker</title><link href="https://jon.eus/posts/20180108-ssl-doan-eff-i-esker" rel="alternate" type="text/html" title="SSL doan EFF-i esker" /><published>2018-01-08T00:00:00+01:00</published><updated>2018-01-08T00:00:00+01:00</updated><id>https://jon.eus/posts/ssl-doan-eff-i-esker</id><content type="html" xml:base="https://jon.eus/posts/20180108-ssl-doan-eff-i-esker"><![CDATA[<p>Domeinu eta zerbitzari hau duela gutxi berritu zen, baina ez nuen HTTPS jartzeko
aukera eta gogorik izan. Prokrastinazioaren gauzak, alajaina.</p>

<p>Egun hauetan Pocket eta Feedly-ren ordez <a href="https://wallabag.org">Wallabag</a> eta
<a href="https://tt-rss.org">Tiny Tiny RSS</a> erabiltzera pasatu naiz. Norbere ostalarian
instalatu behar diren (<em>self-hosted</em>, ingelesez) zerbitzuak dira. Egunen batean
instalazio gidak euskara itzuliko ditut, bi proiektuak interesgarriak dira eta.
Beno, TT-RSS <a href="https://miniflux.org">miniflux</a> oraindik garapen fasean dagoelako
nago erabiltzen. TT-RSS-ren garatzailea inozo bat delako, nolabait esateko.</p>

<p>Tresna bi hauek (eta beste hainbestek) SSL erabiltzea gomendatzen dute.
Garestiak direla eta, orain arte ez dut SSL ziurtagiririk erabili.
<a href="https://eff.org">EFF</a>-k <a href="https://letsencrypt.org">Let’s Encrypt</a> doako
ziurtagiriak eskeintzen zituela gogoratu nintzen, eta azkenean hortan jarri
naiz.</p>

<p>Zerbitzari honen sistema eragilea Debian da, eta nginx erabiltzen dut web orriak
zerbitzatzeko, alderantzizko proxy bezala. Hau kontuan hartuta, oso eraza da
prozesu osoa. Hemen duzue gidatxoa.</p>

<p>Lehenik eta behin, Let’s Encrypt instalatuko dugu, nginx-eko pluginarekin:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>apt-get update
<span class="gp">$</span><span class="w"> </span>apt-get <span class="nb">install </span>certbot python-certbot-nginx
</code></pre></div></div>

<p>Gero, nginx-en zerbitzatzen diren domeinuei ziurtagiria(k) jarriko di(zki)egu:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>certbot <span class="nt">--nginx</span>
</code></pre></div></div>

<p>Hemen <em>prompt</em> interaktibo bat azalduko da, hobespenak eskatuz: aukeratutako
domeinu eta azpidomeinuak, zerbitzatzeko modua (HTTP zuzena ala ez), zure
eposta, etab. Alde batetik, zertifikatua sortuko du eta bestetik,
<code class="language-plaintext highlighter-rouge">/etc/nginx/sites-available</code>-ko fitxategietan SSL konfigurazioa erantsiko da.
Beraz, orain nginx birkargatzea falta da:</p>

<div class="language-console highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gp">$</span><span class="w"> </span>service nginx reload
</code></pre></div></div>

<p>Bejondeizula, orain zure web orrialdeetara HTTPS bidez sar zaitezke!<sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup></p>

<p>Hau ez da guztia. Irakurri dudanaren arabera, ziurtagiri hauek hiru hilabetero
iraungitzen dira, beraz aldizka eguneratu behar dira. Horretarako <code class="language-plaintext highlighter-rouge">cron</code> lan bat
ezarriko dugu:</p>

<pre><code class="language-consle">$ crontab -e
</code></pre>

<p>Eta fitxategi honetako amaieran zera jarriko dugu:</p>

<pre><code class="language-crontab">30 2 * * 1 /usr/bin/letsencrypt renew
</code></pre>
<p>Orain ez zara zure ziurtagirien egoeraz kezkatu behar.<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup></p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">

      <p><a href="https://ssllabs.com">SSL labs</a>-en arabera ziurtagiriaren kalitatea oso ona
da: B bat. Hau, Diffie-Hellman ahula duelako da. A (onena) nahi baduzu
<a href="https://weakdh.org/sysadmin.html">hemen</a> duzu nola lortu. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
    <li id="fn:2">

      <p>Beno, aholku gisa hobe proiektuaren egoera jarraitu. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#x2934;&#xfe0e;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Jon-</name></author><category term="frikikeriak" /><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jon.eus/static/logo.png" /><media:content medium="image" url="https://jon.eus/static/logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>