If you've discovered something amazing about Perl that you just need to share with everyone,
this is the right place.
This section is also used for non-question discussions about Perl, and for any discussions that are not specifically programming related. For example, if you want to share or discuss opinions on hacker culture, the job market, or Perl 6 development, this is the place. (Note, however, that discussions about the PerlMonks web site belong in PerlMonks Discussion.)
Meditations is sometimes used as a sounding-board — a place to post initial drafts of perl tutorials, code modules, book reviews, articles, quizzes, etc. — so that the author can benefit from the collective insight of the monks before publishing the finished item to its proper place (be it Tutorials, Cool Uses for Perl, Reviews, or whatever). If you do this, it is generally considered appropriate to prefix your node title with "RFC:" (for "request for comments").
This script walks the Linux directory structures to files, while checking ACL access to them and displaying the access rights to all subdirectories.
It can tell you if another user is able to access your files or not, or when used with sudo, check for access of files not owned by you, for any other user on the system.
Native permissions (chmod) are shown in uppercase to distinguish them from ACL permissions (setfacl), which are lowercase.
Let's start with a Usage Example. I naively give user nobody access to t.pl, but as $HOME directories are closed and secure, the actual access is prevented:
TIP: Instead of a find, you can also cat a file with fully qualified files, or echo a file.
#!/usr/bin/perl
use strict;
use warnings;
my $DEBUG = 1;
my $u = $ENV{USR} || $ENV{USER}; # Set default user to check permissio
+ns for
warn "DEBUG: Testing permissions against user '$u'\n" if $DEBUG;
my $g;
my $o;
my %P;
my $file;
while( $file = <STDIN> ) {
chomp($file);
if ($file && -e $file) {
my @F = split /\//, $file;
while(@F){
$P{ join("/", @F) || "/" } = 0; # Build a list of Fully Qu
+alified paths. Deduplicated.
pop @F;
$F[-1] .= "/" if @F; # also add the root path to check
};
}else{
warn "Could not find file '$file' (maybe run this as root to g
+et access to the file?)\n";
}
}
for my $k (sort keys %P) {
my @A = `getfacl "$k" 2>/dev/null | grep -v -e default: -e file:`;
+ # grab output
($o) = map { /# owner: (\S+)/ } @A; # Get the file owner
($g) = map { /# group: (\S+)/ } @A; # Get the file group
grep { s/user::/USER:$o:/} @A; # make native Linux dir/file permis
+sions uppercase
grep { s/group::/GROUP:$g:/} @A; # idem
grep { s/other::/OTHER::/} @A; # idem
$P{$k} = join "\n", grep { !/^#/ && /$u|^other/i } @A;
$P{$k} =~ s/:[^:]+effective:/:/; # consider only effective permiss
+ions
$P{$k} =~ s/\S+:---//g; #remove empty permissions
$P{$k} =~ s/(?:user|group):[\s\S]*\K(other:.*)//mi;
$P{$k} =~ s/[\n\r\s]+/ /g; # remove newlines
$P{$k} = '---' if $P{$k} eq " "; # if no permissions, default to -
+--
};
for my $k (sort keys %P){
print "$k $P{$k}\n";
}
Not really a question, but more like a warning for other users of JIRA-Client-Automated. If this notification doesn't belong here, then please let me know. It's been too long ago since I last visited perlmonks.org, sorry!
I'm using all_search_results in JIRA-Client-Automated to filter out all issues that are assigned to me. The code is here below. The call doesn't work anymore.
I already logged bug https://rt.cpan.org/Public/Bug/Display.html?id=170062
my @open_issues = $jira->all_search_results(
"(((assignee = " . $accountId
. " or assignee = 557058:03251bcc-c6a3-4137-a7f0-d5c63be68d1d9
+)"
. " and project != \"ST - Dev Support\")"
. " or ((assignee is empty or assignee ="
. " 557058:03251bcc-c6a3-4137-a7f0-d5c63be68d1d9 or assignee =
+ "
. $accountId
. ") AND project = \"ST - Dev Support\")) AND status != Done"
. " and status != Cancelled order by created DESC");
Unable to POST /rest/api/latest/search/: 410 Gone{
errorMessages => [
"The requested API has been removed. Please migrate to the /rest/a
+pi/3/search/jql API. A full migration guideline is available at https
+://developer.atlassian.com/changelog/#CHANGE-2046",
],
errors => {},
}
for request:
{
fields => ["*navigable"],
jql => "(((assignee = 557058:488e7764-b837-4c11-974d-ec9115f47e26 or
+ assignee = 557058:03251bcc-c6a3-4137-a7f0-d5c63be68d1d9) and project
+ != \"ST - Dev Support\") or ((assignee is empty or assignee = 557058
+:03251bcc-c6a3-4137-a7f0-d5c63be68d1d9 or assignee = 557058:488e7764-
+b837-4c11-974d-ec9115f47e26) AND project = \"ST - Dev Support\")) AND
+ status != Done and status != Cancelled order by created DESC",
maxResults => 100,
startAt => 0,
} at ./checkJiraIssues.pl line 57.
This week, I had to travel in a regional train, a quite modern Stadler KISS train operated by DB Regio (Deutsche Bahn).
Very unsurprisingly, it has electrical door openers to enter and leave the train. A big round button surrounded by red and green LEDs. Wait until the green LEDs are on, press the button, and the door will open. Easily done even by a three year old kid. I'm old enough to remember trains where you had to push the door open, requiring quite a lot of force.
These modern doors (and that's not limited to the KISS) tend to fail quite often, so DB Regio uses large yellow stickers on the door windows telling you that the door is unfortunately broken and that you should use one of the other doors. Well, that's annoying. You would expect that a door that is used daily by literally thousands of people in the not too extreme weather of Germany to be designed to withstand that use for more than a few months. But that's not the point. The yellow sticker tells you that the door won't open, period.
The KISS train has doors between the segments, designed as a kind of "leaky airlock", with a sealed electric sliding door opened by a small illuminated button on the one side and an unsealed glass swing door on the other side. A very strange design, causing a lot of noise and draught near the glass door, the glass door needs a lot of room in a small area to swing open, and it needs some force to open. Two sliding doors, as in much older trains, would have been the smarter solution.
Now imagine that ugly yellow sticker of shame on the electric sliding door, telling you to use one of the other doors, and the "open" button not being lit. Are they expecting me to climb out of the train at 100 km/h, and enter the next car through one of the outside doors? Probably not. There is a yellow sticker of shame on the door, so it won't open, period.
Or will it? After abour half an hour, someone entered the car through the door. So my thought was "poor guy, now you are trapped in this car, too". I was expecting that only the open button on my side of the door was broken. And he went back to his car, through the door with the yellow sticker. So, yes, the door could not be opened electrically. But it still has handles, and can be opened with a little bit of force. D'oh! I could have travelled in a car with way less people if I had actually tried the handles.
How hard can it be to open a door, again?
Remember that big round buttons with the LEDs, that can open the door when the green LEDs are on? Three of the four cars in a KISS train are equipped with a large lavatory, usable even if you need a wheelchair. One of the big round buttons with the red and green LEDs is mounted next to the door of the lavatory, with the green LEDs permanently on. Guess what happens if you press that button.
If you are unlucky, a voice recording tells you that the lavatory is out of order. Or it tells you that the lavatory is currently in use. In both cases, the door won't open. But, if the lavatory is unused, and you press the button, the voice recoding will tell you exactly that. The door won't move a bit.
This button is not a door opener. It is a method of identifying frequent travelers. If you know the KISS trains, you completely ignore the button and look at the traditional red "WC" light. If it is off, you can enter the lavatory by pulling hard on the door handle. If you don't know the KISS trains, that button will make you look like a fool who does not know the red light.
The official purpose of the button a replacement for the red light for blind and visually impaired persons.
Too bad noboby really thought about the lavatory door. It is huge, to allow entering the lavatory in a wheel chair. Good. But it requires a lot of force to open and close. Little kids can't open the door, and even some adults have problems opening and closing it. So, where is the electrical door opener wired to the infrequent traveler identifier button?
How hard can it be to track working time?
German law forces us to track working time, and that's a good thing. We don't need to track anything more than "working" or "not working". A time stamp clock at the entrance would be sufficient. Except that we sometimes work from the home office, or spend an entire day at a client. Legally, we could even get away with hand-written notes. The law just requires that the working time is recorded, not how.
We work for different clients, sometimes with a fixed price, sometimes we are being paid by the hour, sometimes both at once even in the same project (don't ask). So we recently decided to use a cloud-based time tracking app, which can run in a web broswer, in a desktop application (which is just a browser without an address bar), or in an Android or iOS app (which propably also is just a browser without an address bar).
You can not change your password. Period.
Logout button is hidden behind two menu layers.
There is a permanent reminder (in the browser) to install the desktop application, that you need to click away every single time you log in.
The desktop application refuses to start after installation ("This is not a Windows application")
The Android app is simply unusable. It has the same visual interface as the website, but requires completely different handling than all other Android apps (drag instead of tap for a new record, no way to edit records, and so on).
You can track time only in a calender view:
Short jobs are so tiny in the default zoom level that you can not see them
Long jobs require zooming out and/or scrolling.
You need to open a popup to fix start and stop times, or use zoom and drag-and-drop to adjust start and end times
Zoom requires you to use a special control on the page, you can not use Ctrl + mouse wheel or keyboard shortcuts
You are not allowed to track times of one minute or less. (Not a company policy, the software prohibits that.)
There is no list view of tracked time, period.
About half of the screen width is reserved for unused features, while at the same time project names are cut of due to width restrictions.
The default for the "paid by the hour" switch can be set by the admins for each project. In mixed-payment projects, you may need to change that switch. Which causes more trouble:
Admins can't change switch in tracked time, so lists need to be written and users have to toggle that switches for an entire a month.
Resuming a job resets the switch to the default value instead of keeping the switch as is
And that's only the interface for the "worker bees". I did not even bother to look at the admin stuff, or the reporting that is completely useless unless you are working self-employed.
All we really need is a simple, five-column table:
Start time
End time
Project (from a lookup table)
paid by the hour (checkbox)
Short description for the invoice
Invisible to the user, a sixth column should track the user ID, so working times can be properly summed up, and users see only their own time records.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Recently I needed to display a map with some polygons, markers and popups on it. I wanted to have both an interactive map but also be able to create a hardcopy from my linux's terminal via a script in a headless server.
I found a solution which satisfies both requirements. Have the interactive map be from the HTML produced by LeafletJS and then spawn a headless browser (thank you WWW::Mechanize::Chrome & Corion!!) and take a screenshot of the map, via a script from any headless server.
To me, at least, the screenshot part sounds like a very roundabout way of getting a hardcopy of a map (a PDF or PNG) but after researching this for a few weeks, I realised that this is how it is done in R (and in the serpent world, it is called htmlwebshot).
Building on WWW::Mechanize::Chrome's screenshot functionality and on a conversation I had with LanX some years ago on how to inject JS into a mechanized browser and manipulate the DOM with it I have now published WWW::Mechanize::Chrome::DOMops which finds/deletes elements of the current DOM of your mechanized browser and then on top of that, WWW::Mechanize::Chrome::Webshot which takes a screenshot of your browser contents onto a local file. In short, it renders a URL or a local file onto a, possibly headless, mechanized browser (with all encompassing CSS and JS included), allows some settle time, optionally removing some DOM elements which clutter the view and takes a screenshot of what's currently rendered. I think this is as good as it gets for html2pdf. I mean the browser is the final arbiter on how html renders right? (well, sort of).
https://leafletjs.com/ is really very good at displaying map tiles, images/satellite or vectors, from various sources (e.g. OpenStreetMap for navigation vector maps or ArcGIS/ESRI for satellite images, both free). It is also very easy to draw polygons, markers, etc. on top of the map using map coordinates. And then allows you to move/pan/zoom interactively. Really cool software. Alas in Javascript.
And so, in the below script I combine both to get both a self-contained HTML (it requires lefleat.js external dependency) of an interactive map as well as a printout in the form of PDF/PNG.
Caveat: the output PDF contains only part of the view (increasing the dpi perhaps?) whereas the PNG contains everything the browser window contains. So, a PNG is output instead.
PS: I had in mind to create a Just another Perl Hacker all over Africa but the polyline is quite some bytes long and I will spare you the bandwidth. Just imagine Just another Perl Hacker sprayed all over the globe.
PS2: Geo::Leaflet does a good job at exposing the basic functionality of LeafletJS via Perl. But there are lots more features and options for your map. I propose that once you have a basic HTML map, to template it and keep adding more features there. You do not need to keep using Geo::Leaflet. Check the script's output HTML file.
# by bliako for perlmonks 21/08/2025
use Geo::Leaflet;
use FindBin;
use File::Spec;
use WWW::Mechanize::Chrome::Webshot;
my $lat = 11.1;
my $lon = 22.2;
my $outbase = 'hack';
my $map = Geo::Leaflet->new(
id => "myMap",
center => [$lat, $lon],
zoom => 3,
);
# the tiles are coming from:
$map->tileLayer(
# navigation vector tiles
#url => 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
# satellite images
url => 'https://server.arcgisonline.com/ArcGIS/rest/services/World_
+Imagery/MapServer/tile/{z}/{y}/{x}',
options => {
maxZoom => 19,
maxNativeZoom => 23,
#attribution => 'openstreetmap',
attribution => 'esri',
},
);
$map->polyline(
coordinates => [
[9.0, 20.0],
[11.3, 23.1],
[12.1, 19.4],
], options=>{color=>'red', weight=>'5'}
);
my $map_html = $map->html;
my $outdir = $FindBin::Bin;
my $map_html_outfile = File::Spec->catfile($outdir, $outbase.'_map.htm
+l');
my $FH;
open($FH, '>', $map_html_outfile)
or die "failed to open file for writing html '$map_html_outfile',
+$!";
print $FH $map->html;
close $FH;
my $map_pdf_outfile = File::Spec->catfile($outdir, $outbase.'_map.png'
+);
my $shooter = WWW::Mechanize::Chrome::Webshot->new({
'settle-time' => 10,
'resolution' => '2000x2000',
});
my $local_uri = URI->new('file://'.$map_html_outfile);
$shooter->shoot({
'output-filename' => $map_pdf_outfile,
'url' => $local_uri->as_string,
'remove-DOM-elements' => [
{'element-xpathselector' => '//div[id="leaflet-control-container
+"]'},
],
'exif' => {'created' => 'by the shooter'},
});
print "$0 : done, map saved to PDF '$map_pdf_outfile'\n";
After running across the StringZilla library, it got me thinking that Perl could greatly benefit from similar improvements. After a glance through perlfunc and Module::CoreList the following is a list I think could be targeted for optimization. Thoughts?
I haven't been following along that much, but it seems intriguing.
I have a ton of OOP code using the old-school bless() way of doing things, and after a cursory look at this documentation, my gut says that I shouldn't change anything. There have been so many iterations of OOP modules and such, it just seems that it'll keep changing over and over again. However, with that said, I've been around a long time, and considering almost all of my code will still run on 5.8, Perl is known for its backward-compatibility.
What are your thoughts on this new way of Perl OOP development? Are you embracing it? Are you sticking with the old? For long-time developers, are you considering transitioning?
Hello worthy Monks and Nuns. I'm writing today because on Saturday (a couple
days ago) I had a personal triumph: I got the tool
distcc working across my LAN; at
present providing support to a laptop running Linux from a desktop also running
Linux. The speed-up in intensive compilations of some Perl extension modules is noticeable,
for example, in building modules in the the Digest:: namespace, particularly
with one module (I don't recall for sure which one) which had dozens of XS files
to convert to C and compile.
I had distcc set up on my client machine (the laptop) months ago, at that time
having made the little farm of symlinks recommended as the way to drive distcc in
turn to drive gcc. What I didn't have working and couldn't get a handle on
was the setup on the host(s), where the compilation is performed; in the file
/etc/distcc/clients.allow I needed to define client hostname specifications in CIDR notation (for me, 192.168.1.0/24) for "allowed clients."
Without that set up right, I kept seeing messages from distcc saying connection
refused or variants on that.
Obviously big jobs like building the Linux kernel or Samba are where having
something like distcc is really helpful. But it's just plain cool to have it
working for Perl tasks too.
Soren
Jul 07, 2025 at 16:22 UTC
A just machine to make big decisions
Programmed by fellows (and gals) with compassion and vision
We'll be clean when their work is done
We'll be eternally free yes, and eternally young Donald Fagen —> I.G.Y. (Slightly modified for inclusiveness)
As many of you know nowadays I'm not programming for my work since years. In the not so recent past I've made some stuff for my pure pleasure or just to help a bit here.
The programming communtiy did not cried for this :)
At work I suffered a fistfull of company mergeS and now I'm relegated to boring tasks as boring can be to renew SSL certificates.
Our IT world runs as a mad without a precise destination and strange things happens, as it happened that CA/Browser Forum decided to reduce SSL certificate duration in this way:
after March 15 2026: validity reduced to 200 days
after March 15 2027: validity reduced to 100 days
after March 15 2029: validity reduced to 47 days <--- O_O
But, as we say in Eataly, "not all evils come to harm" and there is a remote possibility I can convice the whole pyramid of my bosses that I can setup some Perl code at least to renew certificates and maybe somewhere install them too.
For sure bosses will complain with: "hey, we have a Dev Dpt here" ..but they act at geological times, and if they insist I can at least propose to setup a demo or better the core functionality we'd like to have distilled into a Perl module (a group of..). This point is important.
I cant let this small chance to fade out, so I must be prepared ( dormitare de fuga cogitante vetat ).
Nowadays Macaroni Group uses Digicert for almost all SSL certificates. They have some APIs for their CertCentral (the new, shiny, fancy, fashion web interface). I asked to tech support if they have also a SandBox environment (money is involved) and they didnt even know the term.. :(
So here I'm, after this long rant, to ask you how to plan my strategy in the right way.
A base module to use automation-api let say Digicert::Automation. Maybe there is the need to have a base module for the general API: service-apis
Ideally this module should be public even if I already fear the testing part.
A serie of other modules using the above, private to the company I work for, to manage: customers, contacts, mail, orders info e renewals etc.
a small DB to record customers, their certificates, contact informations, internal contact.. I'd like to keep this as small as possible, ideally an SQLite one.
a CLI tool to inspect orders, renew certificates etc.. using the above modules and DB.
?? a web interface? I'd skip this part, but it depends how bosses see it.
a cron job to run daily using the above CLI to monitor orders and automatically renew expiring ones.
What I'd like from your part at the moment are: suggestion on the big picture, its design implementation, on hoW to start coding the base module, previous experience in this.. and whatever you think is important to take in count.
Hopefully this is the first of many request on the matter.
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
While my strategy was optimal like the proposed solution, they claimed the formal proof that there can't be any better solution to be "too technical" to be published there.
(Pierre de Fermat giggles in his tomb).
The attempts in the comment section didn't impress me either.
Anyway I spent the last hours figuring out an elegant proof for a general formula of any numbers of cards.
But the comment section there is long closed and I thought the local crowd here would like to try their best too ...:)
I sit on a Program Advisory Committee for a local college as an industry representative, and at next week's meeting we're going to be asked about 'AI in the workforce'. They'll be asking about specific areas, a) How organizations are integrating AI tools, b) Whether AI can be used as a supplement or replacement, and c) What implications AI has for productivity and skill sets.
What do you think college graduates should know about AI? How much do you think they should rely on AI tools? Is vibe coding a real thing?
For a long time, I had a link in my .sig going to Groklaw. I heard that as of December 2024, this link is dead. Still, thanks to PJ for all your work, we owe you so much. RIP Groklaw -- 2003 to 2013.
About two years ago, Veritasium posted The Riddle That Seems Impossible Even If You Know The Answer on Youtube. Today i was rewatching that video, because after seeing it initially i had some doubts, and it was a bit of an itch i finally decided to scratch.
The basic riddle goes something like this (watch the video for a much more coherent explanation AND the solution):
You have 100 prisoners, each with a number.
There is a room with 100 (numbered) boxes, and every prisoner number is in one random box.
Prisoners enter the room one by one
Each prisoner can open 50 boxes and search for their prisoner number.
Each prisoner has to leave the room exactly as he found it.
If ALL prisoners find their own number, everyone goes free.
If even a single prisoner fails to finds his number, everyone stays in jail.
Prisoners can decide on a tactic BEFORE the event, but can't communicate in any way DURIN the event.
If prisoners just do random sampling, their chances are 0.5**100 = 0.0000000000000000000000000000008.
Is there a better tactic? (Rest of the post in spoiler tags if you want to have a go on the problem yourself).
Frankly, even having programmed a full simulation of the solution myself, it still absolutely boggles my mind that this actually works at all. Maths is weird.
Brothers and sisters, fellow Monks (lend me your ears),
I have recently discovered that there is still quite a lot of hope for
using a smartphone as a tool for empowering people and not enterprises.
Android is providing a very potent program: the Android Debug Bridge (ADB)
which communicates with an Android device connected to your desktop (via USB or in same wifi network). With this program, one can tell the device to wake up, to enter the passcode of the screensaver, to navigate to the home screen, to open apps, to close apps, to swipe, to click, to input text. To get readings from sensors, to get a screenshot or a screenvideo and finally to dump the current screen's UI as XML which can then be parsed to find widgets of interest, e.g. a button to click, a textbox to enter text, a list of contacts, etc.
The two main problems with controlling your smart device in such a way are: 1) Android API differences between versions, so standard apps or widgets are named differently. 2) Android remembers to notify you about something when in the middle of controlling an app and steals the focus. But neither of these problems is
insurmountable.
The idea of controlling a device from my desktop is very appealing. In fact, I do not use a real device but an emulator (A note of warning here, better use an emulator or an unimportant phone).
At first a friend wanted to keep tapping on an app in order to gain some points for an idiotic competition. Then I wanted to send viber and skype messages from the command line of my linux terminal. And so I have set out to make a thin wrapper to the ADB for Perl. There are a lot of such wrappers for a lot of environments but I did not see one for Perl yet. So here it is : Android::ElectricSheep::Automator
use Android::ElectricSheep::Automator;
my $mother = Android::ElectricSheep::Automator->new({
'configfile' => $configfile,
'verbosity' => 1,
# we already have a device connected and ready to control
'device-is-connected' => 1,
});
$mother->tap({position=>[1,2]});
use Android::ElectricSheep::Automator::Plugins::Viber;
my $vib = Android::ElectricSheep::Automator::Plugins::Viber->new({
configfile=>'config/plugins/viber.conf', 'device-is-connected' => 1
+});
$vib->open_viber_app();
$vib->send_message({recipient=>'My Notes', message=>'hello%sMonkees
+'});
$vib->close_viber_app();