Mccranky's Blog

Turn On, Boot Up, Jack In

Coding along with the book Wicked Cool Shell Scripts- 101 Scripts for Linux, OS X, and UNIX Systems.

This is the script from Page 11:

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
#!/bin/bash

in_path()
{
cmd=$1
ourpath=$2
result=1
oldIFS=$IFS
IFS=":"

for directory in $ourpath; do

# If i double quoted `$ourpath`, it will not word split, and the loop will only run once.

if [ -x "$directory/$cmd" ]; then
result=0
fi
done

IFS=$oldIFS
return $result
}

checkForCmdInPath()
{
var=$1

if [ ! "$var" = "" ]; then
if [ "${var:0:1}" = "/" ]; then
# Checks whether the command represented by the `$var` is an absolute path or not.
if [ ! -x "$var" ]; then
return 1
fi
elif ! in_path "$var" "$PATH"; then
return 2
fi
fi
}

Positional parameters

See here

A Quick Word

It is good practice to put double quotes around variables in Bash because it prevents word splitting and globbing.

  • Word splitting is the process of breaking up a string into separate words based on whitespace. If a variable contains spaces, without quotes, Bash will treat each space-separated word as a separate argument. This can cause unexpected behavior if the variable is used as an argument to a command.

  • Globbing is the process of expanding wildcard characters such as * and ? into a list of matching filenames. If a variable contains a glob character, without quotes, Bash will try to expand it into a list of matching filenames. This can also cause unexpected behavior if the variable is used as an argument to a command.

By putting double quotes around variables, Bash treats the variable as a single argument, preserving any whitespace or glob characters within the variable. This helps to ensure that the variable is interpreted correctly and the script behaves as expected.

Special variables

$IFS

The internal field separator (IFS) is a special variable in Bash that specifies the delimiter used to separate fields in a string. By default, the IFS is set to whitespace (i.e., space, tab, and newline characters).

`$?

Display the return values of functions.

1
echo $?

You can use it immediately after calling a function with return value.

Slice

[ "${var:0:1}" = "/" ];

The slicing starts at index 0 and lasts for the duration of a single character.

Compare

String comparison

= tests if two strings are equal. For example, if [ "$string1" = "$string2" ] would be true if $string1 and $string2 have the same value.

Pattern matching

== tests if a string matches a pattern using globbing, which is a way to match filenames based on wildcard characters. For example, if [[ "$string" == a* ]] would be true if $string starts with the letter “a”.

I ran into this hassle the other day when my npm command failed to work in the command line. It took me a while to sort things out and left me in a foul mood. To prevent something like that from happening again, I decided to write this post. Nothing fancy - just some commands that might prove helpful in the long run.

node

Display global installation directory

1
npm root -g

If you installed node using the official package installer, the global installation directory for npm packages would be:

/usr/local/lib/node_modules

Or you could’ve installed it using Homebrew. In that case, the global installation directory would be:

/opt/homebrew/lib/node_modules

View global installation

1
npm ls -g
/opt/homebrew/lib
├── @e-hentai/home@1.6.0-alpha.9
├── express-generator@4.16.1
├── nodemon@2.0.22
└── npm@9.6.5

Update global installation

1
npm update -g

View global configuration

1
npm config list

The output should be on the lines of this:

; "builtin" config from /opt/homebrew/lib/node_modules/npm/npmrc

prefix = "/opt/homebrew" 

; "user" config from /Users/Mccranky/.npmrc

fetch-retry-maxtimeout = 300000 

; node bin location = /opt/homebrew/Cellar/node/20.0.0/bin/node
; node version = v20.0.0
; npm local prefix = /Users/Mccranky
; npm version = 9.6.5
; cwd = /Users/Mccranky
; HOME = /Users/Mccranky
; Run `npm config ls -l` to show all defaults.

From it, we can discern a few key instances that might prove helpful.

“builtin” config is stored at /opt/homebrew/lib/node_modules/npm/npmrc

“user” config is stored at /Users/Mccranky/.npmrc

Add/remove configuration

1
npm config set <name> <value>

For example, if I want to specify a range of time before timeout occurs, I can use the following command:

1
2
3
4
npm config set fetch-retry-maxtimeout 300000 // 5 minutes

npm config set fetch-retry-mintimeout 60000 // 1 minute

The same mechanism applys when it comes to how we delete configurations:

1
2
3
4
npm config delete fetch-retry-maxtimeout

npm config delete fetch-retry-mintimeout

express

I’ve only just started dabbling with express and my expertise is cut pretty thin, but the rule of thumb I tend to follow is:

  1. If you’re installing something that you want to use in your program using require('something'), then install it locally, at the root of your project.

  2. If you’re installing something that you want to use on the command line or something, install it globally, so that its binaries end up in your $PATH environment variable.

Based on this, you would want to install express-generator using the -g flag as you will use it as a command line tool, but you’d want to install express without this flag as it’s a module you will want to require() it in your application.

The key aspect of this demo is that the utilization of an immediately executing function in JavaScript generates a fresh variable scope, which distinguishes it from if, else, and while. The code presented below exemplifies this fact.

1
2
3
4
5
6
7
8
9
10
11
12
var foo = 123

if (1) {
var foo = 456
}

(_ => {
var foo = 123
})()

console.log(foo)

Output:

456

Notice how the function does not reset the value of variable foo? Now that’s something to be mindful of!

Puppeteer is a Node.js library that provides a high-level API to control headless Chrome or Chromium browsers. It is widely used for web scraping, testing, and automation, and is an essential tool for many developers who work with web applications.

Note that I’ll be demonstrating on ArchLinux

Because Puppeteer relies on Node.js, the first thing we do is create a project directory and initiate npm.

1
2
3
4
5
6
7
8
9
10
11
12
mkdir puppeteer-project;

cd puppeteer-project;

npm init -y

npm i puppeteer --save

sudo pacman -S libx11 libxcomposite libxdamage libxext libxi libxtst nss freetype2 harfbuzz

# Puppeteer requires some additional dependencies to be installed

Now we write our script:

1
vim puppeteer.js

The script should be on the lines of this template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const puppeteer = require('puppeteer');

(async () => {
const browser = await puppeteer.launch({
executablePath: '/usr/bin/chromium',

// We can also drop this line and instead, set an environment variable in Bash.

// `$ export PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium`

headless: true
});
const page = await browser.newPage();
await page.goto('https://www.example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();

This code will launch Chromium in headless mode and navigate to https://www.example.com, take a screenshot of the page, and then close the browser.

More content about Puppeteer coming up!

Installation

To install puppet server first add the upstream GPG key:

$ gpg --fetch-keys https://yum.puppetlabs.com/RPM-GPG-KEY-puppet-20250406
Then install the puppetserverAUR package.
1
2
3
4
5
6
git clone https://aur.archlinux.org/puppetserver.git

cd puppetserver/

makepkg -si

Having questions about the makepkg command? Visit here!

Afterwards, enable and start the puppetserver service.
1
2
3
4
5
6
sudo systemctl enable puppetserver.service

# Add to "/etc/systemd/system/multi-user.target.wants".

sudo systemctl start puppetserver.service

Delete a key

List the keys in your keyring using the command gpg --list-keys:

$ gpg --list-keys
/root/.gnupg/pubring.kbx
------------------------
pub   rsa4096 2019-04-08 [SC] [expires: 2025-04-06]
      D6811ED3ADEEB8441AF5AA8F4528B6CD9E61EF26
uid           [ unknown] Puppet, Inc. Release Key (Puppet, Inc. Release Key) <release@puppet.com>

For example, the key ID of the instance above is “D6811ED3ADEEB8441AF5AA8F4528B6CD9E61EF26”.

Delete the key using the command gpg --delete-keys [key ID].

Note that deleting a key from your keyring will prevent you from verifying any signatures made with that key in the future. If you need to use the key again later, you will need to fetch it again using the gpg --fetch-keys command.

Configuration

The Puppet Server’s configuration files are stored in /etc/puppetlabs/puppetserver/.

Solution

Our fix to the problem is to remove /mnt/share entirely and mount something else in its place.

This is the portion of the startup process which showed the error:

[FAILED] Failed to mount /mnt/share.
See 'systemctl status mnt-share.mount' for details

By the way, this post is for those who followed my last tutorial on using Samba service to mount a shared directory on ArchLinux VM.

Check mount unit status

We’ll start by following the instruction to check the status of the mount unit by running the suggested command:

1
systemctl status mnt-share.mount

This will give us more information about the specific error that occurred.

Warning: The unit file, source configuration file or drop-ins of mnt-share.moun>
x mnt-share.mount - /mnt/share
     Loaded: loaded (/etc/fstab; generated)
     Active: failed (Result: exit-code) since Thu 2023-04-27 02:45:46 UTC; 40mi>
      Where: /mnt/share
       What: //localhost/share
       Docs: man:fstab(5)
             man:systemd-fstab-generator(8)
        CPU: 28ms

Apr 27 02:45:46 alarm systemd[1]: Mounting /mnt/share...
Apr 27 02:45:46 alarm mount[379]: mount error(111): could not connect to ::1mou>
Apr 27 02:45:46 alarm systemd[1]: mnt-share.mount: Mount process exited, code=e>
Apr 27 02:45:46 alarm systemd[1]: mnt-share.mount: Failed with result 'exit-cod>
Apr 27 02:45:46 alarm systemd[1]: Failed to mount /mnt/share.

Side Content

Check file system properties

Since we’ve decided to remove the mount /mnt/share instead of trying to fix it, we shall proceed to learn a little about how to mount a disk. For instance, if we want to mount an NTFS file system and ensure that the file system is accessible and error-free, we can use the following command to check it for errors:

1
2
3
4
5
6
7
sudo pacman -S ntfs-3g

# Install the `ntfs-3g` package which provides the `ntfsfix` tool.

sudo ntfsfix /dev/sda1

# Replace `/dev/sda1` with the appropriate device and partition.

If the virtual hard disk has multiple partitions, we’ll need to determine which partition contains the NTFS file system we want to mount. Oftentimes we use the lsblk command to list the available storage devices and their partitions, and the blkid command to list the UUIDs of the partitions.

$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sr0     11:0    1 1024M  0 rom  
vda    253:0    0  9.8G  0 disk 
|-vda1 253:1    0  200M  0 part /boot
`-vda2 253:2    0  9.6G  0 part /

In my case, the virtual machine has a single virtual hard disk, which is identified as /dev/vda. This virtual hard disk has two partitions, /dev/vda1 and /dev/vda2, which are mounted at /boot and /, respectively.

/dev/vda1 is a 200MB partition formatted as a Linux file system such as ext4 or xfs, and contains the kernel and other boot files.

/dev/vda2 is a 9.6GB partition also formatted as a Linux file system, and contains the root file system for the Arch Linux operating system.

Mount NTFS file system

If we want to mount an additional NTFS file system on our virtual machine, we can create a new directory to use as the mount point, such as /mnt/ntfs, and then add an entry to the /etc/fstab file to mount the NTFS file system at that mount point.

For example, if the NTFS file system is located on /dev/vda3, we can add the following line to the /etc/fstab file:

1
/dev/vda3 /mnt/ntfs ntfs-3g defaults 0 0

Or if you’ve run blkid and looked up the UUID of the file system you wanted to mount, you can also swap the line above for the following one:

1
2
3
UUID=12345678-1234-1234-1234-1234567890ab /mnt/ntfs ntfs-3g defaults 0 0

# Pretend for a sec that the UUID of `/dev/vda3` is "12345678-1234-1234-1234-1234567890ab"

After adding the entry to the /etc/fstab file, we need to run sudo mount -a. This should mount the NTFS file system at the specified mount point, and the mount point should be automatically mounted at boot time.

Remove Samba entries

Edit Samba’s configuration file /etc/samba/smb.conf and remove everything in the [mnt] field.

Then, navigate to /etc/fstab and comment out anything associated with /mnt/share:

# share /mnt/share 9p trans=virtio,nofail 0 0
# //localhost/share /mnt/share cifs user=mccranky,password=Rogue12 0 0

Since we’ve already removed Samba service on our machine, we have no need of checking whether if the mount options specified in the mount unit are correct. But if you haven’t removed it yet, feel free to edit the mount unit file located at /etc/systemd/system/mnt-share.mount and modify the mount options.

Remove the mount unit for /mnt/share:

1
sudo rm /etc/systemd/system/mnt-share.mount

Reload the systemd daemon to ensure that the changes take effect:

1
sudo systemctl daemon-reload

When we check the status of mnt-share.mount, we should get:

 $ sudo systemctl status mnt-share.mount
x mnt-share.mount
     Loaded: not-found (Reason: Unit mnt-share.mount not found.)
     Active: failed (Result: exit-code) since Thu 2023-04-27 02:45:46 UTC; 1h 5>
        CPU: 28ms

Apr 27 02:45:46 alarm systemd[1]: Mounting /mnt/share...
Apr 27 02:45:46 alarm mount[379]: mount error(111): could not connect to ::1mou>
Apr 27 02:45:46 alarm systemd[1]: mnt-share.mount: Mount process exited, code=e>
Apr 27 02:45:46 alarm systemd[1]: mnt-share.mount: Failed with result 'exit-cod>
Apr 27 02:45:46 alarm systemd[1]: Failed to mount /mnt/share.

Last we can finally run sudo rm -r /mnt/share to remove /mnt/share from our machine.

Perfect! Now when we reboot again we should receive no errors.

Install Dependencies

SPICE guest tools

See SPICE guest tools

SPICE WebDAV

SPICE WebDAV is required for QEMU directory sharing as an alternative to VirtFS.

Since we’re on ArchLinux, we should run the following command:

1
sudo pacman -S phodav

Now we should want to visit the shared directory.

Normally, it is exposed as a WebDAV mount on the guest’s localhost (typically on port 9843).

To access it, we need a browser.

Firefox

I don’t have one yet, so I’ll Install Firefox via yay.

1
yay -S firefox

Before we move on, let’s configure the DISPLAY environment variable first. Again, I need to install one:

1
2
3
sudo pacman -S xorg xorg-xinit xfce4

# Once installation is complete, `reboot` and log-back-in

Before we proceed, make sure to check the following conditions:

X Window System is actually running: You can start the X Window System by running the command startx in a terminal window.

You have permission to access the X Window System: You may need to add your user account to the video group by running the command sudo usermod -aG video <username>.

X Window System is configured to allow remote connections: You may need to edit the /etc/X11/xinit/xserverrc file to include the -listen tcp option. For example, you can add the line exec /usr/bin/X -listen tcp to the file.


We may face some problems when we run startx because X server requires some sort of display device or screen so that it can display graphical output, and since ArchLinux is text-based, we’ll have to go through a few extra steps.

  • Run sudo pacman -S xf86-video-fbdev to install the xf86-video-fbdev package. This package provides a generic framebuffer driver that can be used in place of a specific display driver.

  • Edit the /etc/X11/xorg.conf.d/10-monitor.conf file to specify the fbdev driver. We can do this by adding the following lines to the file:

1
2
3
4
Section "Device"
Identifier "fbdev"
Driver "fbdev"
EndSection

That should do the trick when we run startx again.

If the X server still fails to start, you may need to investigate further by checking the /var/log/Xorg.0.log file for additional information about the error.


After double-checking the conditions listed above, we can now run the command export DISPLAY=:0 to set the display environment variable to the default value for the X Window System.

At last we launch Firefox and navigate to http://127.0.0.1:9843.

1
firefox http://127.0.0.1:9843

We can also try running Firefox with the --no-remote option. This option tells Firefox to open a new instance of the browser, rather than connecting to an existing instance.

1
firefox --no-remote http://127.0.0.1:9843

If the SPICE WebDAV service is running correctly, you should be able to see the page in the Firefox browser window.

Headless browser

Puppeteer

See here

i2pdbrowser

Clone this repo:

1
git clone https://github.com/PurpleI2P/i2pdbrowser.git

Navigate to the README.md file for more information

For this tutorial, we’ll be using Samba. As for what Samba really is though, the most I can figure out from my search on Google is that Samba is a free and open-source software that allows files to be shared across Windows and Linux systems simply and easily. To be exact, it is an open-source implementation of the SMB/CIFS protocol.

Setup

Install smbclient util with pacman

1
sudo pacman -S smbclient

Create shared directory

1
sudo mkdir /home/<user>/share

This directory is to be shared between the host and guest machines.

Edit the Samba configuration file

Open up the configuration file for samba:

1
sudo nano /etc/samba/smb.conf

Add these lines to the configuration file:

1
2
3
4
[share]
path = /home/<user>/share
read only = no
guest ok = yes

Create Samba password

1
sudo smbpasswd -a <user>

Restart the Samba service to refresh:

1
sudo systemctl restart smb.service

IP Configuration

In the UTM app on your MacBook, go to the settings for the ArchLinux VM and enable the “Port Forwarding” option. Add a new rule with the following settings:

Protocol: TCP
Host Port: 445
Guest IP: IP address of the ArchLinux VM
Guest Port: 445

To get Guest IP, run the following line:

1
[root@alarm ~]# ip addr | grep inet
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host 
inet 192.168.65.3/24 metric 1024 brd 192.168.65.255 scope global dynamic enp0s1
inet6 fde3:e977:b4d3:5c13:e0b4:51ff:fee5:2142/64 scope global dynamic mngtmpaddr noprefixroute 
inet6 fe80::e0b4:51ff:fee5:2142/64 scope link

In this case, it’s 192.168.65.3.

To get Host IP, run the following line:

1
2
3
ipconfig getifaddr en0

# 10.8.189.52

On your MacBook, open Finder and click “Go” > “Connect to Server” (Cmd + K).

Enter this address: smb://localhost:445/share

Enter the Samba username and password when prompted.

You can now access the shared directory and transfer files between the host and guest operating systems.

Mount /mnt/share

Normally during the boot-up process of our machines, the mounting up of disks and folders are done for us. However, I keep getting this error telling me:

[FAILED] Failed to mount /mnt/share.

So I have to mount this directory myself, by running:

1
sudo mount -t cifs //localhost/share /mnt/share -o user=<Samba username>,password=<Samba password>

This command mounts a Samba share located on the local machine (localhost) to a directory (/mnt/share) using the Common Internet File System (CIFS) protocol.

The -o option specifies additional mount options, in this case, it provides the Samba username and password to authenticate and access the share.


Enable Samba service

But before we run this command, we have to ensure that Samba service on the ArchLinux VM is up and running.

Check that the Samba service is running on the ArchLinux VM:

1
sudo systemctl status smb.service

If the service is not running, start it using the following command:

1
sudo systemctl start smb.service

To automatically start the Samba service on boot, you can enable the smb.service unit running the following command:

1
sudo systemctl enable smb.service

Make sure that the Samba username and password are correct.

1
smbclient //localhost/share -U mccranky

Restart the ArchLinux VM to test that the Samba service starts automatically:

1
sudo systemctl reboot

To check whether /mnt/share has been successfully mounted, run the following line:

1
mount | grep /mnt/share

If the directory is mounted, we should be able to see something similar to this:

//localhost/share on /mnt/share type cifs (rw,relatime,vers=3.1.1,cache=strict,username=mccranky,
uid=0,noforceuid,gid=0,noforcegid,addr=127.0.0.1,file_mode=0755,dir_mode=0755,soft,nounix,serveri
no,mapposix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1,closetimeo=1,use
r=mccranky)

Mount /mnt/share on startup

To automatically mount the Samba shared directory on boot, you can add an entry to the /etc/fstab file.

1
sudo nano /etc/fstab

Then append the following line to the end of the file:

1
//localhost/share /mnt/share cifs user=mccranky,password=Rogue12 0 0

However, it seems that our new input comflicts with this line:

1
share /mnt/share 9p trans=virtio,nofail 0 0

The reason for this is because our new line mounts a CIFS file system from localhost onto the mount point /mnt/share, using the username mccranky and password Rogue12.

The old line mounts a 9p file system onto the same mount point /mnt/share, using the virtio transport and the nofail option.

Since our old entry gave us much headache, I’ll just swap it for the new one. :)

Let’s test the mount by running the following command:

1
sudo mount -a

This command will attempt to mount all entries in the /etc/fstab file. If there are any errors, it will display them in the terminal.

Now we run sudo systemctl reboot to see if everything has been resolved at boot-up. There should be no more failures.

Rollback

Disable Samba service

1
2
3
4
5
6
7
8
9
10
11
12
13
sudo systemctl stop smb.service

sudo systemctl disable smb.service

sudo pacman -R samba

sudo rm -rf /etc/samba
sudo rm -rf /var/cache/samba
sudo rm -rf /var/lib/samba

sudo userdel -r samba
sudo groupdel samba

Unmount /mnt/share

Edit the Samba configuration file /etc/samba/smb.conf using a text editor:

1
sudo nano /etc/samba/smb.conf

Find the section that defines the /mnt/share share. It should look something like this:

1
2
3
4
[mnt]
path = /mnt/share
read only = no
guest ok = yes

Remove the entire section, then restart the Samba service:

1
sudo systemctl start smb.service

The /mnt/share share should now be removed from Samba on Arch Linux.

Revoke Samba password

1
sudo smbpasswd -x <user>

This will remove the user’s password from the Samba password database, effectively undoing the sudo smbpasswd -a <user> command.

ArchLinux is a text-based operating system that does not come with a graphical interface, and all tasks are performed by running commands in the Command Line Interface (CLI).

Setup

The setting up of UTM and running virtual machines on it is rather simple. Just follow the steps shown below and you’ll be playing around soon enough.

  1. Download UTM

  2. Click on Open in UTM - this automatically redirects you to your newly installed UTM app, where UTM will download the pre-built ArchLinux VM for you.

  3. (Optional) You can run the VM as is, but feel free to tweak with the settings if you want to.

Install Dependencies

sudo

1
2
3
4
5
6
su -

pacman -Syu

pacman -S sudo

su is short for “substitute user”, and it is used to switch to another user account in Unix-based operating systems. When you use su without any options, it will switch to the root user account by default.

The - option used with su is used to simulate a full login for the new user, and it is not specific to the root user. When you use su - followed by a username, it will switch to that user’s account with a login shell.

So, to summarize:

  • su is used to switch to another user account.

  • su without any options will switch to the root user account by default.

  • su - followed by a username will switch to that user’s account with a login shell, simulating a full login for that user.


pacman

pacman is the package manager for Arch Linux, a lightweight and flexible Linux distribution.

With pacman, users can easily install, remove, and update software packages on their Arch Linux system. It uses a binary package format, which means that packages are precompiled and ready to install, making the process faster and more efficient than compiling from source.

Some common pacman options include:

pacman -Syu: -S stands for “sync”, -y and -u are options that tell pacman to refresh the package databases and upgrade all packages, respectively. -Syu, as a whole, updates the system and all installed packages to the latest version.

pacman -S <package>: -S is a shorthand for --sync. This command installs a package. When --needed option is specified alongside the pacman -S command, only packages that are not already installed on your system get installed.

pacman -R <package>: -R stands for “remove”. This command removes a package.

pacman -Ss <searchterm>: -Ss stands for “synchronize/search”. This command searches for packages containing the specified search term.

pacman -Q: -Q stands for “query”. This command lists all installed packages on the system.

Use the following commands with caution!

pacman -Sc: Removes all the packages from the cache which are not currently installed on the system. It will only remove packages that are not needed anymore and will not affect any installed packages. This command can be useful to free up disk space on the system.

pacman -Scc: Removes all the packages from the cache, including those that are currently installed on the system. It will remove all the package files from the cache, along with their associated databases. This command can be useful if you want to completely clean the package cache and start fresh.

pacman -Syy: Forces a refresh of all package databases, even if they are already up to date. This ensures that you have the latest package database information available, which can be useful in situations where the package databases may have become out of sync or corrupted.


Once the installation is complete, we need to configure sudo to allow users to execute commands with administrative privileges. To do this, you need to add the user to the wheel group. Run the following command to add the user to the wheel group:

1
usermod -aG wheel <username>

This command is used to add a user to the wheel group, which will give them the ability to perform administrative tasks on the system using the sudo command.

usermod: This is a command-line utility in Unix-based operating systems that is used to modify user account properties. The usermod command allows you to add or remove a user from a group, change a user’s home directory, and modify other user account settings.

wheel: This is a special group in Unix-based operating systems that is used to control access to administrative tasks. Users who are members of the wheel group are allowed to use the sudo command to execute commands with root privileges.

-aG: These two options used alongside usermod are used to add a user to a group. Specifically, -a stands for “append”, which means that the user is added to the group without removing them from any other groups they may already be a member of. -G stands for “group”, and is followed by the name of the group to add the user to.


1
visudo -f /etc/sudoers

visudo: This is a command used in Unix-based operating systems to edit the sudoers file, which controls user access to administrative commands.

-f: This option is used to specify the file to edit.

visudo uses the system’s default editor to open and edit the sudoers file, which is often vi.

If vi is not your thing, you can always specify which editor to use by pass EDITOR=<editor-name> in front of visudo. You can change the default editor once and for all by change these two environment variables: VISUAL and EDITOR.

1
export EDITOR=nano

Note
The main difference between the two is that VISUAL is used for visual editors, such as Sublime Text, Atom, or Visual Studio Code, while EDITOR is used for non-visual editors, such as nano, vim, or emacs.

Let’s add the finishing touch and uncomment the following line in the sudoers file:

1
%wheel ALL=(ALL:ALL) ALL

SPICE guest tools

SPICE stands for Simple Protocol for Independent Computing Environments. It is a remote computing solution that allows users to access the desktop of a virtual machine or remote system from a client device. SPICE provides a high-performance, low-latency connection that supports a wide range of features, including audio, video, and USB redirection. It is commonly used in virtualization environments, such as those provided by QEMU and KVM, to provide remote access to virtual machines.

However, we’re using it for clipboard sharing. With SPICE guest tools installed, the clipboard will be synced between the guest and the host.

Install the spice-vdagent package by running the following command:

1
sudo pacman -S spice-vdagent

Once the installation is complete, start the spice-vdagent service by running the following command:

1
sudo systemctl start spice-vdagentd.service

You can also enable the service to start automatically at boot time by running the following command:

1
sudo systemctl enable spice-vdagentd.service

However, I wasn’t able to enable it on first try.

The unit files have no installation config (WantedBy=, RequiredBy=, Also=,
Alias= settings in the [Install] section, and DefaultInstance= for template
units). This means they are not meant to be enabled or disabled using systemctl.

Possible reasons for having this kind of units are:

* A unit may be statically enabled by being symlinked from another unit's
  .wants/ or .requires/ directory.
* A unit's purpose may be to act as a helper for some other unit which has
  a requirement dependency on it.
* A unit may be started when needed via activation (socket, path, timer,
  D-Bus, udev, scripted systemctl call, ...).
* In case of template units, the unit is meant to be enabled with some
  instance name specified.

Here are some potential reasons why this error might be occurring and how we can address them:

The unit file might be missing the [Install] section. Check the spice-vdagentd.service file located in /usr/lib/systemd/system to see if it contains an [Install] section with the appropriate WantedBy or RequiredBy settings. If the section is missing or incomplete, you can add it manually. For example, to enable the service at boot time, you can add the line WantedBy=multi-user.target to the [Install] section.

The unit file might be a template unit. Template units are designed to be instantiated with specific instance names and cannot be enabled or disabled directly. Check the spice-vdagentd.service file to see if it contains the DefaultInstance setting in the [Install] section. If it does, you will need to specify an instance name when enabling the service using the systemctl enable command. For example, if the DefaultInstance setting is my-instance, you would run systemctl enable spice-vdagentd@my-instance.service.

The unit file might be symlinked from another unit’s .wants/ or .requires/ directory. Check the contents of these directories located in /etc/systemd/system to see if there are any symlinks pointing to spice-vdagentd.service. If there are, you do not need to enable the service separately as it will be started automatically when the dependent unit is started.

It’s the first fix for me. My [Install] section had only one line “Also=spice-vdagentd.socket“, so I added a second.

wget

Install the wget command-line tool:

1
2
3
4
5
sudo pacman -Syy

# Update package database

sudo pacman -S wget

Note: You may need to refresh your keychains first!

git

Install the git package by running the following command:

1
sudo pacman -S git

yay

The reason why we’re not installing apt is because apt is a package manager used in Debian-based Linux distributions like Ubuntu, and it is not available in Arch Linux. Instead, Arch Linux uses its own package manager called pacman, the one we just talked about.

If you are familiar with apt and want to use a similar package manager in Arch Linux, you can use yay, which is a popular AUR (Arch User Repository) helper that provides a pacman-like interface with added features.

1
sudo pacman -S base-devel

Install yay by running the following command:

1
2
3
4
5
6
git clone https://aur.archlinux.org/yay.git

cd yay

makepkg -si

makepkg -si is a command used in Arch Linux to build and install a package from source code.

makepkg: This is a tool that automates the process of building packages from source code in Arch Linux. It creates a package file that can be installed using the package manager.

-s: A flag that tells makepkg to install any dependencies needed to build the package.

-i: A flag that tells makepkg to install the package after it has been built.

neovim

1
sudo pacman -S --needed neovim

Create a non-root user

Before we move on to the next step, we have to create an alternative user apart from our current root, otherwise makepkg -si won’t work.

It’s fairly simple.

To create a non-root user account on Arch Linux, we have to run these few steps:

Run the following command to create a new user account:

1
useradd -m -s /bin/bash <username>

Set a password for the new user account:

1
sudo passwd <username>

Add the new user to the wheel group to allow them to use sudo:

1
usermod -aG wheel <username>

At last, we simply log out of the root user account and log in to the new user account by entering the username and password we just created.


Once the installation is complete, you can use yay to search for and install packages from the AUR. For example, to install the firefox package from the AUR, you can run the following command:

1
yay -S firefox

Or if you want to uninstall, run the following command:

1
yay -Rns firefox

This command will remove Firefox and its dependencies (-R), including any configuration files (-n) and any packages that were installed as dependencies and are no longer required (-s).

Now, yay will automatically download and install the package and its dependencies.

Note
While yay provides a pacman-like interface, it is not a drop-in replacement for apt, and there may be some differences in the way packages are managed and installed.


Refresh keys

PGP keys are used to verify the authenticity of packages in the official Arch Linux repositories.

Update the keyring package by running the following command:

1
sudo pacman -Sy archlinux-keyring

Import the new keys by running the following command:

1
sudo pacman-key --populate archlinux

Refresh the keyring by running the following command:

1
2
3
sudo pacman-key --refresh-keys

# This command retrieves the latest keys from the keyserver and update your keyring accordingly.

Now your keychains should be up to date and you should be able to verify the authenticity of packages in the official Arch Linux repositories.

Poweroff

Once you had your fun, you’d probably want to poweroff. Here’s what you should do:

1
sudo poweroff

Or:

1
sudo shutdown -h now

题目

有若干大整数,需要对其进行求和操作。

输入格式

每行输入一个字符串代表一个大整数,连续输入若干行,当某行字符为e或E时退出。

输入样例:

1
2
3
42846280183517070527831839425882145521227251250327
55121603546981200581762165212827652751691296897789
e

输出样例:

1
97967883730498271109594004638709798272918548148116

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})

let sum = BigInt(0)

rl.on('line', line => {
if (!line.localeCompare("e", undefined, { sensitivity: "base" })) {
console.log(sum.toString())
rl.close()
} else {
sum += BigInt(line)
}
})

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.Scanner;
import java.math.BigInteger;

public class Main {
public static void main (String[] args) {
Scanner scanner = new Scanner(System.in);
BigInteger sum = BigInteger.ZERO;

while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.equalsIgnoreCase("e")) {
System.out.println(sum.toString());
break;
} else {
sum = sum.add(new BigInteger(line));
}
}
scanner.close();
}
}
0%