-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathmakeit-startup.sh
More file actions
308 lines (260 loc) · 11.7 KB
/
Copy pathmakeit-startup.sh
File metadata and controls
308 lines (260 loc) · 11.7 KB
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
#!/usr/bin/env bash
# Author: 1RaY-1 (https://github.com/1RaY-1)
# LICENSE: MIT (see LICENSE file)
currentv=1.3 # <-- Version
# Description:
# A program to set scripts to run at startup on Linux in few clicks (so at every boot a needed script executes automatically, thanks to a .service file)
# It supports bash, python, or other INTERPRETED scripts
# if you face some issues, see https://github.com/1RaY-1/linux-startup/blob/main/README.md#problems
# Or create an ISSUE here: https://github.com/1RaY-1/linux-startup/issues
# Tested on: Pop_!OS 22.04 (LTS), Linux Mint (older version), Arch Linux (older) , Debian (older version)
# Fedora (older version, SELinux probably needs to be set to 'permissive')
#
# Run this script only with BASH, it won't work with ZSH, SH
# TODO
# improve the .service file
# Ask user if the startup script should be restarted every time it stops
# Add an option to rename the .service file
# (Maybe) Add an option to create a text file with a list of those commands (stop, start service file, etc...) mentioned at the end
# Test it more & Make it more stable/reliable
# Add SELinux type to the .service file on Fedora, RHEL
# exit on any error
set -e
# colors
readonly green="\e[32m"
readonly red="\e[31m"
readonly reset="\e[0m"
# Some variables
override_service_file=0 # <-- ZERO means NO
# this function checks if a new release of linux-startup is available
version_check(){
latestv=$(curl -s https://api.github.com/repos/1RaY-1/linux-startup/releases/latest | grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
if (( $(echo "$latestv > $currentv" |bc -l) )); then
echo -e "A new version of Linux Startup is available: ${green}$latestv${reset}\n"; sleep 0.5s
fi
}
# be able to exit and print a text at the same time
die(){
echo -ne "$1"
exit
}
# configure
configure(){
# Before it worked when I was typing the RELATIVE path to a script, but now it apparently just doesn't work
printf "Enter the full path of the script that you wanna set as a startup\n(Note: Variables like \$PWD, \$HOME, etc... won't work here)\n${red}>>> ${reset}"
read target_file
echo -ne "
Do you wanna move this script to other directory?
Options:
1-- No (skip this)
2-- Move it to $( [ -d "/usr/local/sbin" ] && echo "'/usr/local/sbin/'" || echo "'/usr/local/sbin/' ${red}DOESN'T EXIST${reset}" )
3-- Move it to $( [ -d "/lib/systemd/system-sleep" ] && echo "'/lib/systemd/system-sleep/'" || echo "'/lib/systemd/system-sleep' ${red}DOESN'T EXIST${reset}")
4-- Move it to other dicrectory (you'll type it)
"
printf "${red}>>>${reset} "
read choice
temp_target_file=${target_file%.*}.service
temp_target_file=${temp_target_file##*/}
target_service_file=${temp_target_file}
# I had problems when tried to move service files to '/etc/systemd/user/' so i use '/etc/systemd/system/' instead
dest_dir_for_target_service_file=/etc/systemd/system/
case $choice in
1)
if [ -f $(pwd)/${target_file} ]; then
dest_dir_for_target_file=$(pwd)/
else
dest_dir_for_target_file="${target_file%/*}"
fi
move_target_file_to_another_dir=0 # false
;;
2)
dest_dir_for_target_file=/usr/local/sbin/
move_target_file_to_another_dir=1 # true
;;
3)
dest_dir_for_target_file=/lib/systemd/system-sleep/
move_target_file_to_another_dir=1
;;
4)
echo "Enter a directory: "
printf "\n${red}>>>${reset} "
read dest_dir_for_target_file
move_target_file_to_another_dir=1
;;
*)
printf "\n${red}Your option is not valid!\n${reset}"
exit 1
;;
esac
unset choice
# detect the non-root user (because the script is supposed to be executed as ROOT)
if [ -n "$SUDO_USER" ]; then
ruser="$SUDO_USER"
#elif [ -n "$LOGNAME" ]; then # apparently this isn't needed, but I'm just gonna let itcommented for now
# REAL_USER="$LOGNAME"
elif [ -n "$USER" ] && [ "$USER" != "root" ]; then
ruser="$USER"
#else # this is probably not needed either
# ruser=$(id -un 1000 2>/dev/null || echo "unknown")
fi
# Ask if want to execute the script (at every boot) as root or as a user
echo -e "\nDo you want the script to be executed as root or as $ruser ?
Options:
1 --- Execute as a user ($ruser)
2 --- Execute as root"
printf "\n${red}>>>${reset} "
read choice
case $choice in
1) id_choice="user" ;;
2) id_choice="root" ;;
*) echo "Invalid answer!" ; exit 1 ;;
esac
unset choice
}
# Check for problems before proceeding
check_if_ok(){
printf "Checking some things..."
sleep 0.8
problems=()
# check if the init system is systemd
if ! [[ `command -v systemctl` ]]; then
problems+=("Your distribution is not using 'systemd'!")
fi
# check if running with elevated privileges
if [ $EUID -ne 0 ]; then
problems+=("Please run me with sudo!")
fi
# check if needed directory exists
if [ $move_target_file_to_another_dir -eq 1 ]; then
if [ ! -d $dest_dir_for_target_file ]; then
problems+=("Directory: '${dest_dir_for_target_file}' does not exist!")
fi
fi
# check if needed file exists
if [ ! -f ${target_file} ]; then
problems+=("File: '${target_file}' does not exist!")
else
# check if needed files contains shebang
read -r firstline<${target_file}
[[ ! $firstline == "#!"* ]] && problems+=("Please add a shebang to '${target_file}'! Read about shebang here: https://en.wikipedia.org/wiki/Shebang_(Unix)")
unset firstline
fi
if [ ${#problems[@]} -ne 0 ]; then
printf "\n${red}Some problems occurred:${reset}\n\n"; sleep 0.8s
for eachProblem in "${problems[@]}"; do echo -e "${red}*${reset} $eachProblem"; done
exit 1
else
# Check if the service file (that were gonna create) already exists
if [ -f "${dest_dir_for_target_service_file}${target_service_file}" ]; then
echo -ne "${red}[Warning]${reset}"; sleep 0.8s
echo -e "\nThe service file ${dest_dir_for_target_service_file}${target_service_file} already exists"
echo "I'm supposed to name the new service file the same as the startup script (at least as for now)"
echo -e "\nAre you willing to override it?"
echo "Y -- Just override it and proceed"
echo "N -- Skip and abort"
printf "\n${red}>>>${reset} "
read choice
case $choice in
Y | y | yes | YES)
echo -ne "${green}Proceeding${reset}\n"
override_service_file=1
sleep 0.8s
;;
*)
echo -ne "${red}Aborting...${reset}"
sleep 0.8s
exit ;;
esac
else
printf "${green}OK${reset}\n"
fi
fi
unset problems
}
# ask user if proceed or no
ask_if_proceed(){
echo "
These things will be performed:
$( [ $move_target_file_to_another_dir -eq 1 ] && echo "* Move '$target_file' to '$dest_dir_for_target_file'" || :)
* Make '${target_file##*/}' executable
$( [ $override_service_file -eq 1 ] && echo "* Override (the existant) '${dest_dir_for_target_service_file}${target_service_file}'" || echo "* Create and edit '${dest_dir_for_target_service_file}${target_service_file}'" )
* Reload daemon
* Enable service '${target_service_file}' "
printf "\nProceed? [y/n]\n${red}>>>${reset} "
read is_ok
case $is_ok in
y | Y | yes | YES) : ;;
*) exit 0;;
esac
unset is_ok
}
# make script startup
register_on_startup(){
if [ $move_target_file_to_another_dir -eq 1 ]; then
printf "Moving ${target_file} to ${dest_dir_for_target_file} ...";sleep 0.8
sudo mv $target_file $dest_dir_for_target_file
# If everything's fine, it'll print the OK msg, otherwise exit
#printf "${green}OK${reset}\n"
[[ $? -eq 0 ]] && printf "${green}OK${reset}\n" || die "${red}Something went wrong${reset}\n"
target_file=${dest_dir_for_target_file}/${target_file##*/}
fi
# Change perms of the exec file
printf "Changing permissions for ${target_file} ...";sleep 0.8
sudo chmod +x ${target_file}
# If everything's fine, it'll print the OK msg, otherwise exit
[[ $? -eq 0 ]] && printf "${green}OK${reset}\n" || die "${red}Something went wrong${reset}\n"
target_file=${target_file##*/} # <-- I think this code shouldn't give any errors
# Detect the user again (if needed)
if [ $id_choice == "root" ] ; then
# # Do not remove underscores from this variable
config_for_target_service_file="[Unit]\nDescription=Startup_script\n\n[Service]\nExecStart=${dest_dir_for_target_file}/${target_file}\n\n[Install]\nWantedBy=multi-user.target\n"
elif [ $id_choice == "user" ] ; then
# detect the non-root user (because the script is supposed to be executed as ROOT)
if [ -n "$SUDO_USER" ]; then
ruser="$SUDO_USER"
#elif [ -n "$LOGNAME" ]; then
# REAL_USER="$LOGNAME"
elif [ -n "$USER" ] && [ "$USER" != "root" ]; then
ruser="$USER"
#else
# ruser=$(id -un 1000 2>/dev/null || echo "unknown")
fi
config_for_target_service_file="[Unit]\nDescription=Startup_script\n\n[Service]\nUser=$ruser\nGroup=$ruser\nExecStart=${dest_dir_for_target_file}/${target_file}\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n"
#config_for_target_service_file="[Unit]\nDescription=Startup_script\n\n[Service]\nExecStart=${dest_dir_for_target_file}/${target_file}\n\n[Install]\nWantedBy=multi-user.target\n"
fi
printf "Editing ${dest_dir_for_target_service_file}${target_service_file} ...";sleep 0.8
printf "${config_for_target_service_file}" > "${dest_dir_for_target_service_file}${target_service_file}"
[[ $? -eq 0 ]] && printf "${green}OK${reset}\n" || die "${red}Something went wrong${reset}\n"
printf "Reloading daemon...";sleep 0.8
sudo systemctl daemon-reload
[[ $? -eq 0 ]] && printf "${green}OK${reset}\n" || die "${red}Something went wrong${reset}\n"
printf "Enabling service: ${target_service_file} ...";sleep 0.8
sudo systemctl enable ${target_service_file}
[[ $? -eq 0 ]] && printf "${green}OK${reset}\n" || die "${red}Something went wrong${reset}\n"
echo -en "\n${green}Done!${reset}"; sleep 0.8s
# print some useful info
echo -e "
Your script will now execute at every boot.
${green}Do ${red}not${reset} forget that:
${red}*${reset} You can ${green}edit${reset} '${dest_dir_for_target_service_file}${target_service_file}' at any time (with sudo)
${red}*${reset} You can ${green}start${reset} (right now) '${target_service_file}' with: sudo systemctl start ${target_service_file}
${red}*${reset} You can ${green}check${reset} the status of '${target_service_file}' with: systemctl status ${target_service_file}
${red}*${reset} You can ${green}disable${reset} '${target_service_file}' with: sudo systemctl disable ${target_service_file}
${red}*${reset} You can ${green}remove${reset} '${target_service_file}' with: sudo rm ${dest_dir_for_target_service_file}${target_service_file}
"
}
main(){
# supposing 'wget' and 'curl' are installed and there is internet connection, a quick check for updates will be performed
# but user won't be forced to update
if [[ `command -v curl` ]] && [[ `command -v wget` ]] &> /dev/null; then
wget -q --spider https://github.com/1RaY-1/linux-startup/releases
if [ $? -eq 0 ]; then
version_check
fi
fi
configure
check_if_ok
ask_if_proceed
register_on_startup
}
main