Local Linux User Tries FreeBSD
arnavion.dev
arnavion.dev
> shell things
(duplicating from other comments) Bash is indeed not in FreeBSD base; it's easy to install it, but not installing it is also a valid choice. The default login shell doesn't make a big difference, you can use chsh to change that. I also agree POSIX sh isn't quite enough for a lot of scripts.
> [ sysfs, procfs]
These are sort of available, but really just for compatibility with Linux binaries; take a look at the man pages for linsysfs and linprocfs. Just a note to say they're not totally missing, but I would agree they probably don't contain what you're looking for anyway.
> In some cases the sysctl output is not easily machine-parseable. For example, the uptime information from sysctl -n kern.boottime
Depending on how easy it is to process binary values, sysctl -b kern.boottime could be useful here; you'd get two raw integers.
> FreeBSD's netstat -I em0 -bin returns a tabular display,
You might try netstat -I re0 -bin --libxo json or similar. libxo was added in FreeBSD 11.0, and I think got plumbed to the networking commands at least (I see it's not hooked to sysctl in 12.0, so probably not in whatever 11.X pfSense is on either, although it would be useful). check man xo_parse_args for more details.
> nothing recognizes --help
--help is a GNUism; usually the BSD version is -h (although, not for netstat), and yeah, the included help text isn't super useful unless you know what the things mean... pfSense is intended for resource constrained systems, which I guess justifies no man text... but I'd install it it's possible, it's super useful.
> Perl would probably be another good choice
(this isn't accurate, as noted by comments) Perl is a nice choice on FreeBSD, because it is part of the base system (unlike, as you noted, bash). This can sometimes be a bit tricky, if you want a new perl feature, but as long as you're writing run of the mill perl (which everything described here should fit), as long as it's not a positively ancient system, you should be ok.
Anyway; it looks like you've learned quickly; enjoy!
It also works for the thermal sysctls - they appear to output 4-byte unsigned integers in deci-Kelvins. Eg 3061 is 306.1 K == 33.0 degrees Celsius.
`netstat ... --libxo json` does work, though parsing JSON from awk isn't trivial either. The best way I can think of is to use `json,pretty` which puts one key-value-pair per line, which I could then filter for the specific keys I want. But it would amount to as much or more effort as the non-JSON parser makes.
pfSense doesn't have `jq` by default but does have `uclcmd`. I got as far as `netstat -I em0 -bin --libxo json | uclcmd get -f - -j '.statistics.interface'` to get an array of JSON objects, but any attempt to apply a transformation to each element of this array (there are no manpages for it online, but its Github readme implies the existence of an `each` function) caused the program to segfault.
This largely misses the point. The output of sysctl(8) is not intended to be machine readable. Instead of parsing strings you should be using sysctl(3) directly or through whatever bindings for your language of choice.
That's essentially what sysctl(8) is. Unlike Linux though the text interface isn't really intended to be the primary API. The article discusses using Rust and C which both have access to sysctl(3).
Also pfSense is a constrained environment wothout all the feature of a full FreeBSD install.
> --help is a GNUism; usually the BSD version is -h (although, not for netstat), and yeah, the included help text isn't super useful unless you know what the things mean...
OTOH, FreeBSD's man pages[0] are superb compared to that of Linux for most subjects. I usually don't bother with -h and go straight to the man pages.
As far as Awk over Perl. It's been quite some time but when I did awk scripts they had some pretty annoying quirks that you just had to learn. Perl was just easier. Has that changed? I know that Perl as a larger language is languishing but isn't it still perfect for this type of thing?
I briefly tried FreeBSD. Only briefly, because that ports thing was a mess. My trial lasted only a few days before my system was an unusable mess.
In what way was it a mess?
To show the 10 most recent firewall log entries, the dashboard runs `clog filter.log | tail -10r` (`tail -10r` is the equivalent of `tail -10 | tac`). It would be nice to instead just run `clog -f filter.log` (open filter.log in follow mode, just like `tail -f`), leave it open across dashboard refresh iterations, and maintain an in-memory buffer of the 10 most recent entries for display. It would presumably be more efficient.
However this requires the ability to do a non-blocking read of the command output, which requires `PROCINFO["read_timeout"]`, which is gawk-specific and not available on FreeBSD's default awk.
I don't mind it too much, because repeatedly doing `clog -f | tail -10r` doesn't use that much CPU to be concerned about anyway. Though I may investigate Perl to see if it's possible there.
while (1) {
try_reading_one_more_line( $file_in );
print_last_10_lines_reverse();
sleep( 1 ); # wait, in this case one second
}
and that doing on the opened file $file_in. You'd have to write both functions in the loop of course. But Perl is a real language which allows you to try reading from the point in the file you've reached the last time, without reading anything you've already read again. POSIX semantics allows you to observe that the file grew even if in the previous pass you've hit the end of file. And you even don't have to keep in memory the lines which aren't to be printed anymore.I prefer Perl to any shell scripts, as soon as the script is more than circa 10 lines.
Yes.
>But Perl is a real language which allows you to try reading from the point in the file you've reached the last time, without reading anything you've already read again.
The input in this case is the stdout of a command (clog), so it's not a seekable file.
The flow I've described works on non-seekable files (and pipes). After you reach the end of file in one pass, you are allowed to try to read again in the next, and the file pointer stayed on the same position if you haven't closed the file (and of course you should not close it). If the other process wrote something, the next time read will succeed. If you don't want to display the partial line before the line feed is written, you have to collect the read bytes before you read the line feed. It's all doable in Perl.
The only case I've seen something of what I've described not working was some case under some non-recent version of Wine, and I don't know if they fixed that. Otherwise Perl and POSIX support everything described.
gen_lines.pl:
#!/usr/bin/env perl
$| = 1;
while (1) {
print "line $n\n";
$n++;
sleep( 3 );
}
show_10.pl:
#!/usr/bin/env perl
$u = 1;
@lines = ();
while (1) {
$line = <>;
push @lines, $line;
shift @lines if ( scalar( @lines ) > 10 );
print "10 lines update $u:\n"; $u++;
for $l ( reverse @lines ) {
print $l;
}
sleep( 1 );
}
./gen_lines.pl | ./show_10.plIf you were referring to leaving the file open across multiple iterations, then yes that is already what I said in the first post that you responded to. It's obvious that perl can do it; any program can.
I'm not aware how shell scripts or awk could do that. Maybe you can explain. I knew about Perl and that's what I showed.
In shell, you'd just move the invocation of `foo` outside the dashboard loop, ie `foo | while :; do if read -r line; then ...; fi; sleep 1; done`
The hard part is not to read from the same command across multiple dashboard iterations. The hard part is detecting that there is nothing more to read from the command without blocking, so that the dashboard can continue rendering if there's no more input. As I wrote in the first post that you responded to, gawk has `PROCINFO["read_timeout"]` to help with this (`getline` will return a specific error that the script can detect and break out of the loop), but FreeBSD's awk does not, which is why I was thinking of investigating whether Perl can do it.
In Perl $file->blocking( 0 ) or fcntl with O_NONBLOCK enables non-blocking sysread, I’ve recently used that.
https://perldoc.perl.org/IO/Handle.html
All FreeBSD scripts I encountered use posix shell.
> does have a dependency on perl to get the current time in seconds from the Unix epoch. This is because FreeBSD's date does not have a way to get milliseconds in the time
One could just install the GNU coreutils (probably, not checked though, much less overhead than a full perl install) or kill that problem with very few lines of C.
brew install bash coreutils findutils gawk parallelDefaults matter, and it's helpful when the default shell for command-line use matches the shell used for scripting, because people often do scripting on the command line.
If you need more-than-POSIX in your scripts, then use the proper shebang.
>You can post comments on this blog post by: sending mail to email@address.dev with a subject starting with [blog-2019-10-20-local-linux-user-tries-freebsd]
I wish my day job was this exciting!
So it's slow enough to read out and type out into a text editor, then convert the typeout to its IP, but not slow enough that it's a bother.
I typically end up just nmapping :-/
/usr/bin/morse -l "Soekris rocks" > /dev/led/error
Guess what it does :-)Slackware is one of the very oldest Linuxes, and traditionally used a BSD-flavored 'init' system, rather than a System-V syle init, or even the newer 'systemd'. It has traditionally concentrated on being extremely stable, and more slanted towards server work, though I used it for many years as my main desktop.
Generally you want to automate server management with some sort of config management. While possible with Slackware, it's easier with a Debian or Red Hat style system.
For a desktop Slackware is pretty nice. It's easy to understand and gets out of your way. I used it for over a decade until, one day, I realised I was tired of recompiling slackbuilds after each low level dependency upgrade.
!man netstat
Wouldn't it be a lot easier to use mdns/zeroconf, or static IPs? Or use a label maker and put the MAC address on it, and then use arp-scan?
Local Linux User Tries FreeBSD - You Won't Believe What Happens Next!
(Actually nothing much happened at all. A few differences, but nothing major.)
You can start with popen to some command, then when that's slow, switch to ffi calls.
Would FreeBSD consider POSIX sh as their default shell instead of tcsh?
`#!/bin/sh`
So it doesn't really matter what the login shell is. (As a long-time FreeBSD user, the first thing I always do is install a different shell; I'm not sure who actually likes tcsh.)