2026/03/09(月)MacのLaunchpadで自前スクリプトを動かそうとしたときに shell-init: error retrieving current directory

getcwd: cannot access parent directories: Operation not permitted と出た時の対処法。

Launchctlで自前のスクリプトが動かないエラーの対応法

というブログ記事があってこの通りにするとエラーが解消されましたが、セキュリティ上は好ましくありません。

~/Desktop などに自前のスクリプトを置くとこのエラーが出るようですが、~/~/myproject (一例) に置くとエラーが解消されて動くことが確認できました。

bash にフルディスクアクセス権限を与えずに、場所を変えるのがより良いかと思います。

その他のハマりどころ

スクリプトをいじった後は、

launchctl unload ~/Library/LaunchAgents/test.plist
launchctl load ~/Library/LaunchAgents/test.plist

などでリロードしてやる必要がありました。さもなければ、いじる前の状態のスクリプトで実行され続けます。

2025/06/21(土)PerlでUnicodeの文字集合から特定の部分文字集合を16進数形式で抜き出すやつ

まれによく必要になるのですが、必要になった頃には書き方が思い出せないのでメモ。出力形式などは簡単にカスタマイズできます。

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say/;
use utf8;

my $state = 0;

for (0x0000 .. 0x10FFFF)
{
    $_ = chr;
    my $codepoint = sprintf("%04X", ord);

    if (/\p{Han}/)
    {
        print $codepoint if $state == 0;
        $state++;
    }
    else
    {
        if ($state > 1)
        {
            say "\\t$codepoint";
        }
        elsif ($state == 1)
        {
            say "\n$codepoint";
        }

        $state = 0;
    }
}

出力:

2E80\t2E9A
2E9B\t2EF4
2F00\t2FD6
3005
3006
3007
3008
3021\t302A
3038\t303C
3400\t4DB6
4E00\t9FD6
F900\tFA6E
FA70\tFADA
20000\t2A6D7
2A700\t2B735
2B740\t2B81E
2B820\t2CEA2
2F800\t2FA1E

2023/06/18(日)2023年6月時点においてPerlで画像付きtweetするコード

2022年にPerlで画像付きtweetするコード」というのを書いてあるのですが、こちらがTwitterの仕様変更で使えなくなったので2023年6月版を書きました。

重要ポイント

  1. Twitter API Ver. 1.1 で画像アップロードして media_id を受け取る
  2. Twitter API Ver. 2 で「1」で受け取った media_id をtweets APIで送る

中々変な仕様なのでそのうちTwitter側で変更が入るかもしれません(?)

PerlのCPANモジュール固有の注意点

  • Ver.2 に完全対応はしていないため、 api_version や api_ext のオプションを指定する必要がある
  • update メソッドは Ver.2 に対応していないので request という低レベルAPIでPOSTする必要がある
#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use Twitter::API;

my $twitter_v1_1 = Twitter::API->new_with_traits(
      api_version => '1.1',
      api_ext => '.json',
      traits => [qw/Migration ApiMethods RetryOnError/],
      consumer_key => 'xxx',
      consumer_secret => 'xxx',
      access_token => 'xxx',
      access_token_secret => 'xxx',
);

my $twitter_v2 = Twitter::API->new_with_traits(
    api_version => '2',
    api_ext => '',
    traits => [qw/RetryOnError/],
    consumer_key => 'xxx',
    consumer_secret => 'xxx',
    access_token => 'xxx',
    access_token_secret => 'xxx',
);

my $media = ['/nanka/tekitohna/filepath.png'];
my $ret = $twitter_v1_1->upload_media($media);
my $text = 'ツイートするテキスト';
$twitter_v2->request(post => 'tweets', { -to_json => { text => $text, media => { media_ids => [ $ret->{media_id_string} ] } } });

その他

Twitter APIのアクセス権限回りは https://www.zenryoku-kun.com/post/twitter-api が参考になるかと思います。

2022/05/04(水)2022年にPerlで画像付きtweetするコード

#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use Twitter::API;

my $twitter = Twitter::API->new_with_traits(
    traits => [qw/Migration ApiMethods RetryOnError/],
    consumer_key => 'xxx',
    consumer_secret => 'xxx',
    access_token => 'xxx',
    access_token_secret => 'xxx',
);

my $media = ['/nanka/tekitohna/filepath.png'];
my $ret = $twitter->upload_media($media);
$twitter->update('ツイートするテキスト', { media_ids => $ret->{media_id} });

ちなみに2022年現在、Net::Twitter::Lite からは画像をアップロードできませんでした。もう古いので、モダンな Twitter::API を使うのが良さそうです。

2019/06/05(水)【雨量観測】XRAINのスクリーンショットを会社Slackに投稿するPerlスクリプト

天気情報が流れるチャンネルが会社のSlackにあるのですが、XRAINのスクリーンショットも流れてきてほしくなったので作りました。

ちなみに大学生の頃は大学院の研究室訪問や大学院試験の費用を稼ぐために気象会社でアルバイトしていました。

SlackのtokenとチャンネルIDの取得情報はググってください。

$logo は会社のロゴと矢印が描かれた画像で、矢印の先にオフィスがあるという具合になっています。適当な画像を用意して置き換えてください。

CPANモジュール以外は何か特別にインストール必要なものはありませんでした。

#!/usr/bin/evn perl

use strict;
use warnings;
use utf8;
use Log::Log4perl qw(:easy);
use WWW::Mechanize::Chrome;
use File::Spec;
use File::Basename 'dirname';
use HTTP::Request::Common qw//;
use Encode;
use Furl qw//;
use JSON;
use Imager;
use DDP;

# TODO:
#  * 会社付近の色を取得して雨が降っているか判定

my $dirname = File::Spec->rel2abs(dirname($0));
my $rain_url = 'http://www.river.go.jp/x/krd0207010.php?lon=139.50406730175018&lat=35.674031853779084&opa=0.4&zoom=8&leg=0&intvl=5&ext=0';
my $fn= $dirname . "/xrain.png";
my $logo = $dirname . '/logo_and_arrow.png';

Log::Log4perl->easy_init($ERROR);
my $mech = WWW::Mechanize::Chrome->new(headless => 1);
$mech->viewport_size({ width => 760, height => 780 });
$mech->get($rain_url);
my $png = $mech->content_as_png;

open(my $fh, '>', $fn) or die $!;
binmode($fh);
print {$fh} $png;
close $fh;

my $img = Imager->new;
$img->read(file => $fn) or die $img->errstr;

$img->rubthrough(
  src  => do {
    my $tmp = Imager->new;
    $tmp->read(file => $logo) or die $tmp->errstr;
    $tmp;
  },
  tx => 460,
  ty => 527,
);

$img->rubthrough(
  src  => do {
    my $tmp = Imager->new;
    $tmp->read(file => $logo) or die $tmp->errstr;
    $tmp;
  },
  tx => 1203,
  ty => 527,
);

$img->rubthrough(
  src  => do {
  my $tmp = Imager->new;
    $tmp->read(file => $logo) or die $tmp->errstr;
    $tmp;
  },
  tx => 460,
  ty => 1170,
);
$img->rubthrough(
  src  => do {
    my $tmp = Imager->new;
    $tmp->read(file => $logo) or die $tmp->errstr;
    $tmp;
  },
  tx => 1203,
  ty => 1170,
);

$img->write(file => $fn) or die $img->errstr;

my $req = HTTP::Request::Common::POST('https://slack.com/api/files.upload',
  Content_Type => 'multipart/form-data',
  Content => [
    token    => 'xxxx',
    channels => 'xxxx',
    file     => [$fn],
    title    => Encode::encode_utf8('XRAIN自動投稿'),
    initial_comment => $rain_url,
  ]
);

my $res = Furl->new->request($req);
my $json = Encode::decode_json($res->content);

#p $json;

うまくいけば↓のように投稿されます。cronで定期実行させています。

スクリーンショット_2019-06-05_21_19_07.png