-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstzlma
executable file
·581 lines (512 loc) · 21.3 KB
/
instzlma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
#!/bin/bash
#
# instzlma - install zlma onto a Linux on s390x (mainframe) architecture
# user running this must have sudo access
#
#+--------------------------------------------------------------------------+
function usage()
# Give help to the user
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
echo "instzlma - install zlma onto s390x Linux"
echo "Usage: instzlma [OPTIONS]"
echo ""
echo "OPTIONS:"
echo " -h|--help Give help (this screen)"
echo " -v|--verbose Increase verbosity"
echo " -x|--debug Print commands and arguments as they are executed"
echo ""
exit 51
} # usage()
#+--------------------------------------------------------------------------+
function parseArgs()
# Parse arguments
# Args: All arguments passed into script
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
while [ -n "$1" ] # loop through args passed in
do
case "$1" in
-h|--help)
usage
;;
-v|--verbose)
verbose=2
flags="-v"
;;
-x|--debug) # turn trace on
set -vx
;;
*)
echo "ERROR: Too many arguments: $1"
usage
;;
esac
shift
done
} # parseArgs()
#+--------------------------------------------------------------------------+
function checkBase
# Check that:
# - We are running on s390x (zLinux)
# - The zlma repo is cloned
# - Either 'apache' or 'www-data' user exists
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
if [ ! -f /proc/sysinfo ]; then # not zLinux
echo "ERROR: /proc/sysinfo not found - not running on s390x?"
exit 1
fi
if [ ! -d $HOME/zlma ]; then
echo 'ERROR: zlma repo not found under $HOME'
echo "Try: cd; git clone https://github.com/mike99mac/zlma"
exit 2
fi
id apache > /dev/null 2>&1
if [ $? = 0 ]; then # user exists - assume RHEL-based
webUser="apache"
webDir="/var/log/httpd"
else
id www-data > /dev/null 2>&1
if [ $? = 0 ]; then # user exists - assume Debian-based
webUser="www-data"
webDir="/var/log/apache2"
else
echo "ERROR: neither user 'apache' nor 'www-data' found - exiting" | tee -a $outFile
exit 3
fi
fi
} # checkBase()
#+--------------------------------------------------------------------------+
function verboseMsg
# Write message to stdout when -v|--verbose is set
# Args: message to write
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
if [ "$verbose" -gt 1 ]; then # verbose
echo -e "$@"
fi
} # verboseMsg()
#+--------------------------------------------------------------------------+
function runCmd
# Run a command and exit if it fails
# Args: command to run
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
cmd="$@" # all args
echo " Running: $cmd" | tee -a $outFile
eval $cmd 2>&1
rc=$?
if [ "$rc" != 0 ]; then # it failed
echo "ERROR: $cmd returned $rc - exiting" | tee -a $outFile
exit 4
fi
} # runCmd()
#+--------------------------------------------------------------------------+
function mkDir
# Make specified directory, set owner and group to webUser, set group write bit
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
local theDir=$1
local rc
if [ -d $theDir ]; then # directory exists
echo " directory $theDir already exists"
else # create directory and set attributes
runCmd sudo mkdir -p $theDir
runCmd sudo chown $webUser:$webUser $theDir
runCmd sudo chmod g+w $theDir
fi
} # mkDir
#+--------------------------------------------------------------------------+
function copyAllFiles
# Copy all files from repo directories to new ones
# Arg 1: source dir
# Arg 2: target dir
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
local sourceDir=$1
local targetDir=$2
if [ ! -d $theDir ]; then # directory exists
echo "ERROR: Unexpected - source directory $sourceDir does not exist - exiting" | tee -a $outFile
exit 5
fi
cd $sourceDir
runCmd "sudo cp * $targetDir"
cd $targetDir
runCmd "sudo chown $webUser.$webUser *"
} # copyAllFiles()
#+--------------------------------------------------------------------------+
function copyOneFile
# Copy one file and set ownership to user running the script
# Arg 1: source dir
# Arg 2: source file
# Arg 3: target dir
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
local sourceDir=$1
local sourceFile=$2
local targetDir=$3
runCmd sudo cp $sourceDir/$sourceFile $targetDir
runCmd sudo chown $USER:$USER $targetDir/$sourceFile
} # copyOneFile()
#+--------------------------------------------------------------------------+
function instPackages
# Install packages with either 'apt' or 'dnf'
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
local cmd
echo | tee -a $outFile
echo "Step 1): Installing packages ..." | tee -a $outFile
which apt >/dev/null 2>&1
if [ $? = 0 ]; then # use apt and assume Debian-based
cmd="sudo apt install -y apache2 cifs-utils cmake curl gcc git jq locate make libmariadb-dev mariadb-server net-tools pandoc python3 python3-dev python3-pip python3.12-venv"
runCmd $cmd
echo | tee -a $outFile
echo "Step 2): Setting Apache and mariadb to start at boot time ..." | tee -a $outFile
runCmd sudo systemctl enable apache2 # set Apache to start at boot
else # no apt, check for dnf
which dnf >/dev/null 2>&1
if [ $? = 0 ]; then # use dnf and assume RHEL-based
cmd="sudo dnf install -y bind-utils bzip2-devel cifs-utils cmake curl file gcc git jq libffi-devel make mariadb-connector-c mariadb-connector-c-devel.s390x mariadb-server mlocate net-tools nfs-utils openssl-devel python3 python3-pip tar vim wget zlib-devel"
runCmd $cmd
echo | tee -a $outFile
echo "Step 2): Setting Apache and mariadb to start at boot time ..." | tee -a $outFile
sudo systemctl enable httpd # set Apache to start at boot - ignore non-0 rc
else
echo "ERROR: did not find 'apt' nor 'dnf' - exiting" | tee -a $outFile
exit 6
fi
fi
runCmd sudo systemctl enable mariadb # set mariadb to start at boot
} # instPackages()
#+--------------------------------------------------------------------------+
function mkDirectories
# Create target directories
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
# make 2 CGI dirs, a log file dir and a directory for console data
echo | tee -a $outFile
echo "Step 3): Creating directories ..." | tee -a $outFile
mkDir /srv/www/zlma # CGI R/O
mkDir /srv/www/zlmarw # CGI R/W
mkDir /var/log/zlma # log files
mkDir /srv/consolez # console data
# set attributes of /var/log/'apache|httpd'
echo | tee -a $outFile
echo "Step 4): Modifying directory /var/log/$webDir ..." | tee -a $outFile
cd /var/log
if [ ! -d $webDir ]; then # log dir does not exist
runCmd sudo mkdir $webDir
fi
runCmd sudo chown $webUser:$webUser $webDir
runCmd sudo chmod 750 $webDir
} # mkDirectories()
#+--------------------------------------------------------------------------+
function copyFiles
# Copy files from repo to target directories
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
# copy all files from CGI dirs in repo to new dirs
echo | tee -a $outFile
echo "Step 5): Copying CGI files from repo to /srv/www ..." | tee -a $outFile
copyAllFiles $repoDir/srv/www/zlma /srv/www/zlma
copyAllFiles $repoDir/srv/www/zlmarw /srv/www/zlmarw
# copy files one at a time to /usr/local/sbin
echo | tee -a $outFile
echo "Step 6): Copying scripts from repo to /usr/local/sbin ..." | tee -a $outFile
cd $repoDir/usr/local/sbin
local nextFile
for nextFile in *; do # copy each file to /usr/local/sbin
copyOneFile $repoDir/usr/local/sbin $nextFile /usr/local/sbin
done
copyOneFile $repoDir zlmainfo $HOME # copy zlmainfo to user's home directory
} # copyFiles()
#+--------------------------------------------------------------------------+
function mkSymlinks
# Create symlinks for additional console scripts
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
echo | tee -a $outFile
echo "Step 7): Creating symbolic links ..." | tee -a $outFile
cd /usr/local/sbin
if [ ! -h catcons ]; then # symlink does not exist
runCmd sudo ln -s spoolcons catcons
else
echo " symlink catcons already exists - skipping"
fi
if [ ! -h grepcons ]; then
runCmd sudo ln -s spoolcons grepcons
else
echo " symlink spoolcons already exists - skipping"
fi
if [ ! -h lscons ]; then
runCmd sudo ln -s spoolcons lscons
else
echo " symlink lscons already exists - skipping"
fi
if [ ! -h rmcons ]; then
runCmd sudo ln -s spoolcons rmcons
else
echo " symlink rmcons already exists - skipping"
fi
} # mkSymlinks()
#+--------------------------------------------------------------------------+
function mkVenv
# Make a virtual environment under /srv/venv/
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
cd /srv/
echo | tee -a $outFile
echo "Step 8): Creating virtual environment ..." | tee -a $outFile
/usr/bin/python3.11 -V >/dev/null 2>&1
if [ $? = 0 ]; then # Python 3.11 is installed - use it
pythonCmd="python3.11"
fi
runCmd sudo $pythonCmd -m venv venv
runCmd sudo chown -R $webUser:$webUser /srv/venv
runCmd sudo chmod -R g+w /srv/venv
# make a 'python3' symlink
cd /srv/venv/lib
if [ -d python3.10 ]; then # 3.10 is the venv Python ver
ln -s python3.10 python3
elif [ -d python3.11 ]; then # 3.11 is the venv Python ver
ln -s python3.11 python3
elif [ -d python3.12 ]; then # 3.12 is the venv Python ver
ln -s python3.12 python3
fi
echo | tee -a $outFile
echo "Step 9): Activating venv ..." | tee -a $outFile
runCmd source /srv/venv/bin/activate # activate the virtual environment
echo | tee -a $outFile
echo "Step 10): Upgrading pip ..." | tee -a $outFile
runCmd "$pythonCmd -m pip install --upgrade pip"
} # mkSymlinks()
#+--------------------------------------------------------------------------+
# function buildConnector
# TODO: this is not getting called - should be able to delete it...
# Download and build the mariadb Python connector
#+--------------------------------------------------------------------------+
#{
# : SOURCE: ${BASH_SOURCE}
# : STACK: ${FUNCNAME[@]}
# echo | tee -a $outFile
# echo "Step 11): Building and installing the mariadb connector ..." | tee -a $outFile
# connectorLib="/usr/local/lib/mariadb/libmariadb.a"
# if [ -f $connectorLib ]; then
# echo " The mariadb connector $connectorLib seems to be installed - skipping" | tee -a $outFile
# else # build and install the mariadb connector v3.3.1
# connectorVer="mariadb-connector-c-3.2.6-src"
# tarFile="$HOME/zlma/$connectorVer.tar.gz"
# # wget https://downloads.mariadb.org/connector-c/3.3.1/$tarFile - old file
# cd /tmp
# runCmd tar -xzf $tarFile
# cd $connectorVer
# runCmd "cmake ." | tee -a $outFile
# runCmd "cmake --build ." | tee -a $outFile
# runCmd "sudo cmake --install ." | tee -a $outFile
# if [ ! -f $connectorLib ]; then
# echo "ERROR: Library $connectorLib not found - exiting" | tee -a $outFile
# exit 8
# fi
# fi
#} # buildConnector()
#+--------------------------------------------------------------------------+
function pipPackages
# Install pip packages
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
echo | tee -a $outFile
echo "Step 12): Installing pip packages ..." | tee -a $outFile
for nextPkg in certifi charset_normalizer idna "mariadb==1.1.4" mysql-connector-python packaging ply requests setuptools; do
runCmd "$pythonCmd -m pip install $nextPkg" | tee -a $outFile
done
if [ "$webUser" = apache ]; then # RHEL-based system
runCmd "$pythonCmd -m pip install mariadb==1.1.4" # need older code to not pull in connector/C 3.3.1
else
runCmd "$pythonCmd -m pip install mariadb"
fi
# THIS DID NOT WORK
# distutils is not included in Python 3.12, but mariadb still uses it - kludgy workaround:
# if [ "$webUser" = "www-data" ]; then # Debian-based distro
# mariadbDir="/srv/venv/lib/python3.12/site-packages/mariadb"
# if [ ! -d $mariadbDir ]; then
# echo "ERROR: directory $mariadbDir not found" | tee -a $outFile
# exit 7
# fi
# cd $mariadbDir
# connFile="connections.py"
# if [ ! -f $connFile ]; then
# echo "ERROR: executable file $mariadbDir/$connFile not found" | tee -a $outFile
# exit 8
# fi
# runCmd sudo cp connections.py connections.py.orig
# runCmd sed -i -e "'s/from distutils.version import StrictVersion/from packaging import version/g'" connections.py
# fi
} # pipPackages()
#+--------------------------------------------------------------------------+
function confApache
# Configure Apache
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
echo | tee -a $outFile
echo "Step 13): Configuring Apache" | tee -a $outFile
if [ "$webUser" = "apache" ]; then # RHEL-based: remove -DFOREGROUND and copy mime.types
svcFile="/usr/lib/systemd/system/httpd.service"
if [ ! -f $svcFile.orig ]; then # no backup
runCmd sudo cp $svcFile $svcFile.orig # make a backup
runCmd sudo cp $HOME/zlma/httpd.service.RHEL /usr/lib/systemd/system/httpd.service
runCmd sudo systemctl daemon-reload # reload modified file
fi
runCmd sudo cp /etc/mime.types /etc/httpd/conf # copy mime.types to Apache conf dir
runCmd sudo chgrp apache /run/httpd # change group of run directory
runCmd sudo chmod 770 /run/httpd # change mode to group write
else
svcFile="/usr/lib/systemd/system/apache2.service"
runCmd sudo chmod 770 /var/log/apache2 # change mode to group write
fi
} # confApache()
#+--------------------------------------------------------------------------+
function mkCustom
# fix programs blocking communications such as firewalls and SE Linux
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
echo | tee -a $outFile
echo "Step 14): Customizing environment ..." | tee -a $outFile
runCmd sudo cp $HOME/zlma/bash_profile $HOME/.bash_profile
if [ "$webUser" = "apache" ]; then # RHEL-based:
if [ ! -f /etc/vimrc.orig ]; then
runCmd sudo mv /etc/vimrc /etc/vimrc.orig
runCmd sudo cp $HOME/zlma/vimrc /etc/
fi
if [ -f /etc/zlma.conf ]; then # already exists
echo "/etc/zlma.conf exists - not overwriting"
else # copy it
runCmd sudo cp $HOME/zlma/zlma.conf /etc/
fi
cd /usr/share/vim/vim8*
if [ -f indent.vim ]; then # turn off annoying indent rules
runCmd sudo mv indent.vim indent.vim.dontuse
fi
else # assume Debian-based
if [ ! -f /etc/vim/vimrc.orig ]; then
runCmd sudo mv /etc/vim/vimrc /etc/vim/vimrc.orig
runCmd sudo cp $HOME/zlma/vimrc /etc/vimrc
fi
cd /usr/share/vim/vim9*
if [ -f indent.vim ]; then # turn off annoying indent rules
runCmd sudo mv indent.vim indent.vim.dontuse
fi
cd /usr/share/vim/vim9*/colors
if [ -f desert.vim -a ! -f desert.vim.orig ]; then # replace desert.vim with strange colors
runCmd sudo cp desert.vim desert.vim.orig
runCmd sudo cp $HOME/zlma/desert.vim .
fi
fi
runCmd sudo cp $HOME/zlma/zlma.conf /etc/
} # mkCustom()
#+--------------------------------------------------------------------------+
function fixBlockers
# fix programs blocking communications such as firewalls and SE Linux
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
echo | tee -a $outFile
echo "Step 15): Opening firewall and SE Linux ..." | tee -a $outFile
which firewall-cmd >/dev/null 2>&1
if [ $? = 0 ]; then # there is a firewall-cmd command
runCmd sudo firewall-cmd --zone=public --add-service=http --permanent # open port 80
runCmd sudo firewall-cmd --reload # reload firewall
fi
if [ -f /etc/selinux/config ]; then # SE Linux config file exists
grep "^SELINUX=enforcing" /etc/selinux/config >/dev/null 2>&1
if [ $? = 0 ]; then # SE Linux is enabled
runCmd sudo sed -e 's/SELINUX=enforcing/SELINUX=disabled/g' -i /etc/selinux/config
runCmd sudo setenforce 0 # turn SE Linux off for this session
fi
fi
} # fixBlockers()
#+--------------------------------------------------------------------------+
function restartServices
# Restart mariadb and Apache and show status
#+--------------------------------------------------------------------------+
{
: SOURCE: ${BASH_SOURCE}
: STACK: ${FUNCNAME[@]}
echo | tee -a $outFile
echo "Step 16): restarting mariadb and Apache and checking status..." | tee -a $outFile
runCmd sudo systemctl restart mariadb
echo -n " Status: "
service mariadb status | grep Active:
if [ "$webUser" == "apache" ]; then # RHEL-based
runCmd sudo systemctl start httpd
echo -n " Status: "
service httpd status | grep Active:
else # assume Debian
runCmd sudo systemctl start apache2
echo -n " Status: "
service apache2 status | grep Active:
fi
} # restartServices()
# main()
repoDir="$HOME/zlma" # directory with zlma repo
timeStamp=`date +"%y-%m-%d-%H-%M-%S"` # current date and time
outFile="$HOME/$timeStamp-instzlma.out" # log file
pythonCmd="python3" # can be python3.11
verbose=0 # 1 = verbose
webDir="unknown" # either '/var/log/apache' or '/var/log/httpd'
webUser="unknown" # either 'apache' or 'www-data'
parseArgs $@ # process arguments
checkBase # verify this is s390x
echo "Running instzlma to install zlma at $timeStamp ..." > $outFile # create a new log file
instPackages # install packages
mkDirectories # make target directories
copyFiles # copy from repo to targets
mkSymlinks # create symlinks in /usr/local/sbin
mkVenv # make a virtual environment
#buildConnector # create the mariadb Python connector
pipPackages # install pip packages
confApache # set up Apache
mkCustom # customize environment and vim settings
fixBlockers # fix blockers such as firewall and SE Linux
restartServices # restart mariadb and Apache
let min=$SECONDS/60
let sec=$SECONDS%60
if [ $sec -lt 10 ]; then # add a leading 0
sec="0$sec"
fi
echo
echo "Successfully installed zlma co-reqs in $min:$sec" | tee -a $outFile
echo "Log file: $outFile"