--- doc/install/linux/install.pl 2024/07/27 18:39:10 1.91 +++ doc/install/linux/install.pl 2024/11/26 23:54:22 1.97 @@ -78,7 +78,7 @@ if (!open(LOG,">>loncapa_install.log")) &mt('Stopping execution.')."\n"; exit; } else { - print LOG '$Id: install.pl,v 1.91 2024/07/27 18:39:10 raeburn Exp $'."\n"; + print LOG '$Id: install.pl,v 1.97 2024/11/26 23:54:22 raeburn Exp $'."\n"; } # @@ -437,7 +437,7 @@ sub check_prerequisites { sub check_locale { my ($distro) = @_; - my ($fh,$langvar,$command,$earlyout); + my ($fh,$langvar,$command,$langcmd,$earlyout,$default); $langvar = 'LANG'; if ($distro =~ /^(ubuntu|debian)/) { if (!open($fh,"; chomp(@data); + close($fh); foreach my $item (@data) { if ($item =~ /^\Q$langvar\E=\"?([^\"]*)\"?/) { - my $default = $1; + $default = $1; if ($default ne 'en_US.UTF-8') { if ($distro =~ /^debian/) { $command = 'locale-gen en_US.UTF-8'."\n". @@ -517,8 +518,72 @@ sub check_locale { last; } } - close($fh); - return $command; +# Check for locales + if ($default ne 'en_US.UTF-8') { + my ($has_us_english,$has_other_code,$has_other_lang); + if (open(PIPE,"locale -a 2>/dev/null |")) { + while () { + chomp(); + next if (/^(C(|\.utf8)|POSIX)$/i); + if (/^en_US\.utf8/i) { + $has_us_english = 1; + } elsif (/^[A-Za-z]{2}_[A-Za-z]{2}/) { + $has_other_code = 1; + } elsif (/^[A-Za-z]{3,}/) { + $has_other_lang = 1; + } + } + close(PIPE); + if (!$has_us_english) { + if ($has_other_code || $has_other_lang) { + if ($distro =~ /^ubuntu/) { + $langcmd = "sudo apt-get install language-pack-en\n"; + } elsif ($distro =~ /^debian/) { + $langcmd = "apt-get install language-pack-en\n"; + } elsif ($distro =~ /^(suse|sles)/) { + $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n"; + } elsif ($distro =~ /^fedora(\d+)$/) { + if ($1 > 23) { + $langcmd = "dnf install glibc-langpack-en\n"; + } else { + $langcmd = "yum install glibc-common\n"; + } + } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) { + if ($1 > 7) { + $langcmd = "dnf install glibc-langpack-en\n"; + } else { + $langcmd = "yum install glibc-common\n"; + } + } + } else { + if ($distro =~ /^ubuntu/) { + $langcmd = "sudo apt-get install language-pack-en\n"; + } elsif ($distro =~ /^debian/) { + $langcmd = "apt-get install language-pack-en\n"; + } elsif ($distro =~ /^(suse|sles)/) { + $langcmd = &mt('Use yast: System > Language > Primary Language = English')."\n"; + } elsif ($distro =~ /^fedora(\d+)$/) { + if ($1 > 23) { + $langcmd = &mt('Either install all languages[_1]or install English only[_2]', + ":\ndnf install glibc-all-langpacks\n\n", + ":\ndnf install glibc-langpack-en\n"); + } else { + $langcmd = "yum install glibc-common\n"; + } + } elsif ($distro =~ /^(?:rhes|centos|scientific|oracle|rocky|alma)(\d+)/) { + if ($1 > 7) { + $langcmd = &mt('Either install all languages[_1]or install English only[_2]', + ":\ndnf install glibc-all-langpacks\n\n", + ":\ndnf install glibc-langpack-en\n"); + } else { + $langcmd = "yum install glibc-common\n"; + } + } + } + } + } + } + return ($command,$langcmd); } sub check_required { @@ -529,11 +594,11 @@ sub check_required { } my $gotprereqs = &check_prerequisites($packagecmd,$distro); if ($gotprereqs eq '') { - return ($distro,$gotprereqs,'',$packagecmd,$updatecmd); + return ($distro,$gotprereqs,'','',$packagecmd,$updatecmd); } - my $localecmd = &check_locale($distro); + my ($localecmd,$langcmd) = &check_locale($distro); unless ($localecmd eq '') { - return ($distro,$gotprereqs,$localecmd); + return ($distro,$gotprereqs,$localecmd,$langcmd); } my ($mysqlon,$mysqlsetup,$mysqlrestart,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb, %recommended,$downloadstatus,$filetouse,$production,$testing,$apachefw, @@ -575,7 +640,7 @@ sub check_required { $mysqlrestart = 'sudo '; } $mysqlrestart .= 'service mysql restart'; - return ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart); + return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart); } else { if ($mysqlsetup eq 'noroot') { $recommended{'mysqlperms'} = 1; @@ -604,7 +669,7 @@ sub check_required { $recommended{'stopsrvcs'} = &chksrvcs($distro,$tostop); ($recommended{'download'},$downloadstatus,$filetouse,$production,$testing) = &need_download($distro,$instdir); - return ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow, + return ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow, $mysqlrestart,\%recommended,$dbh,$has_pass,$mysql_unix_socket, $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw, $uses_systemctl,$hostname,$hostip,$sslhostsfilesref,$has_std,$has_int, @@ -667,7 +732,7 @@ sub check_mysql_running { $proc_owner = 'mysql'; $process = 'mysqld'; } - if ($1 >= 15) { + if ($1 >= 12) { $mysqldaemon ='mariadb'; } } elsif ($distro =~ /^suse(\d+)/) { @@ -753,9 +818,15 @@ sub chkconfig { $uses_systemctl{'ntp'} = 1; $uses_systemctl{'cups'} = 1; $uses_systemctl{'memcached'} = 1; - if (($name eq 'sles') && ($num >= 15)) { - $daemon{'ntp'} = 'chronyd'; - $daemon{'mysql'} = 'mariadb'; + if ($name eq 'sles') { + if ($num >= 12) { + $daemon{'mysql'} = 'mariadb'; + } + if ($num >= 15) { + $daemon{'ntp'} = 'chronyd'; + } else { + $daemon{'ntp'} = 'ntpd'; + } } else { $daemon{'ntp'} = 'ntpd'; } @@ -785,7 +856,7 @@ sub chkconfig { (($distro =~ /^debian/) && ($version >= 10))) { $daemon{'ntp'} = 'chrony'; } - if (($distro =~ /^debian/) && ($version >= 11)) { + if (($distro =~ /^debian/) && ($version >= 10)) { $daemon{'mysql'} = 'mariadb'; } } elsif ($distro =~ /^fedora(\d+)/) { @@ -917,11 +988,21 @@ sub check_systemd_security { $service = 'apache2.service'; } system("systemctl daemon-reload"); - if (open(PIPE,"systemctl show $service --property=ProtectHome 2>/dev/null |")) { - my $protection = ; + if (open(PIPE,"systemctl show $service --property=ProtectHome --property=RestrictSUIDSGID 2>/dev/null |")) { + my ($protecthome,$suidsgid); + while (my $line = ) { + chomp($line); + if ($line =~ /^ProtectHome=(read-only|yes)$/i) { + $protecthome = 1; + } elsif ($line =~ /^RestrictSUIDSGID=yes$/i) { + $suidsgid = 1; + } + } close(PIPE); - chomp($protection); - if ($protection =~ /^ProtectHome=(read-only|yes)$/i) { + if ($protecthome) { + return 1; + } + if ($suidsgid) { return 1; } } else { @@ -1989,7 +2070,7 @@ my %prompts = &texthash( print "\n".&mt('Checking system status ...')."\n\n"; my $dsn = "DBI:mysql:database=mysql"; -my ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart, +my ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow,$mysqlrestart, $recommended,$dbh,$has_pass,$mysql_unix_socket,$has_lcdb,$downloadstatus, $filetouse,$production,$testing,$apachefw,$uses_systemctl,$hostname,$hostip, $sslhostsfiles,$has_std,$has_int,$rewritenum,$nochgstd,$nochgint) = @@ -2010,8 +2091,12 @@ if ($mysqlrestart) { exit; } if ($localecmd ne '') { - print "\n".&mt('Although the LON-CAPA application itself is localized for a number of different languages, the default locale language for the Linux OS on which it runs should be US English.')."\n"; - print "\n".&mt('Run the following command from the command line to set the default language for your OS, and then run this LON-CAPA installation set-up script again.')."\n\n". + print "\n".&mt('Although the LON-CAPA application itself is localized for a number of different languages,[_1]the default locale language for the Linux OS on which it runs should be US English.',"\n")."\n\n"; + if ($langcmd ne '') { + print &mt('Use the following command(s) or action(s) to install a required language package.')."\n\n". + "$langcmd\n"; + } + print &mt('Run the following command from the command line to set the default language for your OS,[_1]and then run this LON-CAPA installation set-up script again.',"\n")."\n\n". $localecmd."\n\n". &mt('Stopping execution.')."\n"; exit; @@ -2035,7 +2120,7 @@ if (!$gotprereqs) { &mt('Stopping execution.')."\n"; exit; } else { - ($distro,$gotprereqs,$localecmd,$packagecmd,$updatecmd,$installnow, + ($distro,$gotprereqs,$localecmd,$langcmd,$packagecmd,$updatecmd,$installnow, $mysqlrestart,$recommended,$dbh,$has_pass,$mysql_unix_socket, $has_lcdb,$downloadstatus,$filetouse,$production,$testing,$apachefw, $uses_systemctl,$hostname,$hostip,$sslhostsfiles,$has_std,$has_int, @@ -2904,49 +2989,117 @@ sub check_systemd_update { if (-d '/etc/systemd/system/'.$service.'.d') { if (-e '/etc/systemd/system/'.$service.'.d/override.conf') { if (open(my $fh,'<','/etc/systemd/system/'.$service.'.d/override.conf')) { - my ($inservice,$addservice,$protectoff,$linenum,$change,@lines); + my ($category,$addservice,$protectoff,$changeprot,$suidsgidok,$changesug, + $linenum,%lines,@move,@nocat,@ordered); + $linenum = 0; while (my $entry = <$fh>) { $linenum ++; chomp($entry); - if ($entry eq '[Service]') { - if (!$protectoff) { - $inservice = $linenum; - push(@lines,$entry); + if ($entry =~ /^\s*\[([^\]]+)\]\s*$/) { + $category = $1; + if ($category =~ /^Service$/i) { + push(@ordered,'Service'); } else { - $addservice = 1; - next; + push(@ordered,$category); } - } - if ($entry =~ /^ProtectHome\s*=\s*([\w-]+)\s*$/) { + } elsif ($entry =~ /^ProtectHome\s*=\s*([\w-]+)\s*$/) { my $value = $1; - if ($protectoff) { - next; - if (lc($value) eq 'no') { - $protectoff = $linenum; - push(@lines,$entry); + next if ($protectoff); + if (lc($value) eq 'no') { + if ($category =~ /^Service$/i) { + push(@{$lines{'Service'}},$entry); } else { - if ($protectoff) { - next; - } else { - push(@lines,'ProtectHome=no'); - $protectoff = $linenum; - $change = $linenum; - } + push(@move,$entry); + $changeprot = $linenum; + } + } else { + if ($category =~ /^Service$/i) { + push(@{$lines{'Service'}},'ProtectHome=no'); + } else { + push(@move,'ProtectHome=no'); } + $changeprot = $linenum; + } + $protectoff = $linenum; + } elsif ($entry =~ /^RestrictSUIDSGID\s*=\s*([\w-]+)\s*$/) { + my $value = $1; + next if ($suidsgidok); + if (lc($value) eq 'no') { + if ($category =~ /^Service$/i) { + push(@{$lines{'Service'}},$entry); + } else { + push(@move,$entry); + $changesug = $linenum; + } + } else { + if ($category =~ /^Service$/i) { + push(@{$lines{'Service'}},'RestrictSUIDSGID=no'); + } else { + push(@move,'RestrictSUIDSGID=no'); + } + $changesug = $linenum; + } + $suidsgidok = $linenum; + } else { + next if ($entry =~ /^\s*$/); + if ($category =~ /^Service$/i) { + push(@{$lines{'Service'}},$entry); + } elsif ($category ne '') { + push(@{$lines{$category}},$entry); + } else { + push(@nocat,$entry); } } } close($fh); - if ($addservice || $change || !$protectoff) { + unless (grep(/^Service$/,@ordered)) { + $addservice = 1; + unshift(@ordered,'Service'); + } + if (!$protectoff) { + push(@{$lines{'Service'}},'ProtectHome=no'); + } + if (!$suidsgidok) { + push(@{$lines{'Service'}},'RestrictSUIDSGID=no'); + } + if ($addservice || $changeprot || !$protectoff || $changesug || !$suidsgidok) { if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) { - if ($addservice) { - print $fh "[Service]\n"; + if (@ordered) { + foreach my $category (@ordered) { + print $fh "[$category]\n"; + if (ref($lines{$category}) eq 'ARRAY') { + foreach my $item (@{$lines{$category}}) { + print $fh "$item\n"; + } + } + if ($category eq 'Service') { + if (@move) { + foreach my $item (@move) { + if ($item =~ /^ProtectHome\s*=\s*no\s*$/i) { + unless (grep/^ProtectHome\s*=\s*no\s*$/i,@{$lines{$category}}) { + print $fh "$item\n"; + } + } elsif ($item =~ /^RestrictSUIDSGID\s*=\s*no\s*$/i) { + unless (grep/^RestrictSUIDSGID\s*=\s*no\s*$/i,@{$lines{$category}}) { + print $fh "$item\n"; + } + } else { + print $fh "$item\n"; + } + } + } + } + print $fh "\n"; + } } - foreach my $entry (@lines) { - print $fh "$entry\n"; + if (@nocat) { + foreach my $item (@nocat) { + print $fh "$item\n"; + } } close($fh); print_and_log('Updated /etc/systemd/system/'.$service.'.d/override.conf'); + system('systemctl daemon-reload'); } else { print_and_log('Could not open /etc/systemd/system/'.$service.'.d/override.conf for writing.'); } @@ -2958,9 +3111,10 @@ sub check_systemd_update { } } else { if (open(my $fh,'>','/etc/systemd/system/'.$service.'.d/override.conf')) { - print $fh '[Service]'."\n".'ProtectHome=no'."\n"; + print $fh '[Service]'."\n".'ProtectHome=no'."\n".'RestrictSUIDSGID=no'."\n"; close($fh); print_and_log('Created /etc/systemd/system/'.$service.'.d/override.conf'); + system('systemctl daemon-reload'); } } } else {