SASH(1)

๐Ÿ“ฆ
version 3.8 ยท 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

๐Ÿ’– SASH(1) โ€” stand-alone shell with built-in commands ๐Ÿ’–

okay so bestie, welcome to the General Commands Manual page for sash ๐Ÿ’… this is the iconic stand-alone shell that saves your whole entire system when everything else is giving broken. let's get into it โœจ


๐ŸŒธ NAME ๐ŸŒธ

sash โ€” stand-alone shell with built-in commands


โœจ SYNOPSYS โœจ

(yeah i know it's usually spelled SYNOPSIS but the original said SYNOPSYS so we're keeping that vibe ๐Ÿ’€)

sash [-c command] [-f fileName ] [-p prompt] [-q] [-a] [script]

๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

okay so the sash program is a stand-alone shell and it's literally built for recovering from certain types of system failures. like, imagine your shared libraries are missing or your important executables are gone โ€” sash was created specifically to cope with that kind of disaster ๐Ÿ˜ญ

sash can run external programs, just like any other shell. there are no restrictions on these commands, because the standard shell is used to execute them if there are any non-wildcard meta-characters in the command. periodt.

but here's the real tea ๐Ÿ‘‘ โ€” many of the standard system commands are built-in to sash. these built-in commands are:

-ar, -chattr, -chgrp, -chmod, -chown, -chroot, -cmp,
-cp, -dd, -echo, -ed, -grep, -file, -find, -gunzip,
-gzip, -kill, -losetup, -ln, -ls, -lsattr, -mkdir,
-mknod, -more, -mount, -mv, -pivot_root, -printenv, -pwd,
-rm, -rmdir, -sum, -sync, -tar, -touch, -umount, -where

these commands are generally similar to the standard programs with similar names. however, they are simpler and cruder than the external programs, and so many of the options are not implemented. the restrictions for each built-in command are described later. iykyk.

the built-in commands that correspond to external programs begin with a dash character (-) to distinguish them from the external programs. so typing ls, for example, will attempt to run the real ls program. if -ls is typed, then the built-in command which mimics ls is called. it's giving "dash = built-in" energy ๐Ÿ’…

for the built-in commands, file names are expanded so that asterisks (*), question marks (?), and characters inside of square brackets ([]) are recognised and are expanded. arguments can be quoted using single quotes, double quotes, or backslashes. however, no other command line processing is performed. this includes specifying of file redirection, and the specifying of a pipeline. so no > or | shenanigans with the built-ins, bestie ๐Ÿšซ

if an external program is non-existant or fails to run correctly, then the "alias" built-in command may be used to redefine the standard command so that it automatically runs the built-in command instead. for example, the command "alias ls -ls" redefines "ls" to run the built-in command. this saves you the pain of having to remember to type the leading dash all of the time. if many external programs will not run, then the "aliasall" command may be useful to create multiple aliases. slay.

the "help" command will list all of the built-in commands in sash. if an argument is given, it will list only those built-in commands which contain the given argument as a sub-string. each built-in command is described below in more detail.


alias [name [command]]

if name and command are provided, this defines an alias for a command with the specified name which executes the specified command with possible arguments. arguments containing wildcards can be quoted in order to defer their expansion until the alias is invoked. if just name is provided, then the definition of the specified command alias is displayed. if nothing is provided, then the definitions of all aliases are displayed. it's giving "shortcut queen" ๐Ÿ‘‘

aliasall

this defines aliases for all of the built-in commands that start with dashes to the corresponding names without the dashes. this may be useful when the system is so corrupted that no external programs may be executed at all. like, total system meltdown vibes ๐Ÿ’€

-ar [txp][v] arfile [filename]...

list or extract files from an ar archive. the arfile argument specifies a file name which contains the archive. if no additional filenames are specified, then all files in the archive are operated on. otherwise, only those archive members which have the same name as one of the additional filenames are operated on. filenames which do not appear in the archive are ignored. archives cannot be created or modified. the archiver correctly handles 4.0BSD archives, and understands both the SysV and 4.4BSD extensions for long file names. the extended pseudo-BSD formats are not supported; nor are the two antediluvian binary formats derived from V7 and earlier. (the GNU archiver normally creates archives in the 4.0BSD format with SysV extensions.) so no creating archives, just reading, bestie ๐Ÿ“ฆ

cd [dirName]

if dirName is provided, then the current directory is changed to the dirName. if dirName is absent, then the current directory is changed to the user's home directory (value of the $HOME environment variable). classic cd behavior, no cap ๐Ÿ 

-chattr [+i] [-i] [+a] [-a] fileName ...

change the attributes of the specified files on an ext2 or ext3 file system. using a plus sign (+) adds the specified attribute for the files. using a minus sign (-) removes the specified attributes for the files. the 'i' attribute makes a file immutable so that it cannot be changed. the 'a' attribute makes a file append-only. this command is only available on Linux. so if you're on Linux, you can lock it down ๐Ÿ”’

-chgrp gid fileName ...

change the group id for the specified list of files. the gid can either be a group name, or a decimal value. group chat vibes ๐Ÿ‘ฏ

-chmod mode fileName ...

change the mode of the specified list of files. the mode argument can only be an octal value. so like 755 or 644, not u+rwx or whatever. octal only, bestie ๐Ÿ”ข

-chown uid fileName ...

change the owner id for the specified list of files. the uid can either be a user name, or a decimal value. who owns it? now you do ๐Ÿ‘‘

-chroot path

changes the root directory to that specified in path. this directory will be used for path names beginning with /. the root directory is inherited by all children of the current process. it's giving "new root, who dis?" ๐ŸŒณ

-cmp fileName1 fileName2

determines whether or not the specified file names have identical data. this says that the files are links to each other, are different sizes, differ at a particular byte number, or are identical. so it's a comparison, not a diff, periodt ๐Ÿ”

-cp srcName ... destName

copies one or more files from the srcName to the destName. if more than one srcName is given, or if destName is a directory, then all the srcNames are copied into the destName directory with the same names as the srcNames. copy paste but make it Unix ๐Ÿ’…

-dd if=name of=name [bs=n] [count=n] [skip=n] [seek=n]

copy data from one file to another with the specified parameters. the if and of arguments must be provided, so stdin and stdout cannot be specified. the bs argument is the block size, and is a numeric value (which defaults to 512 bytes). count is the number of blocks to be copied (which defaults to end of file for the input file). skip is the number of blocks to ignore before copying (seek is used if possible, and the default is 0). seek is the number of blocks to seek in the output file before writing (and defaults to 0). any of the numeric decimal values can have one or more trailing letters from the set 'kbw', which multiplies the value by 1024, 512, and 2 respectively. the command reports the number of full blocks read and written, and whether or not any partial block was read or written. it's giving data copying but make it extra ๐Ÿฆ‹

-echo [args] ...

echo the arguments to the -echo command. wildcards are expanded, so this is a convenient way to get a quick list of file names in a directory. the output is always terminated with a newline. so you can be like "what's in here?" and it's like boom, list ๐Ÿ“

-ed [fileName]

edit the specified file using line-mode commands. the following ed commands are provided: = c r w i a d p l s f k z and q. line numbers can be constants, ., $, 'x, /string/ and simple arithmetic combinations of these. the substitute command and the search expression can only use literal strings. there are some small differences in the way that some commands behave. so it's like ed but built-in and a little quirky โœจ

exec fileName [args]

execute the specified program with the specified arguments. this replaces sash completely by the executed program. so it's like, bye sash, hello new program ๐Ÿ‘‹

exit

quit from sash. simple as that. bye bestie ๐Ÿ’–

-file fileName ...

examine the specified files and print out their file type. this indicates whether the files are regular files or not, whether they contain printable text or shell scripts, are executables, or contain binary data. it's giving "what even are you?" energy ๐Ÿ•ต๏ธ

-find dirName [-xdev] [-type chars] [-name pattern] [-size minSize]

find all files contained within the specified directory tree which meet all of the specified conditions. the -xdev option prevents crossing of mount points. the -name option specifies a wildcard pattern to match the last component of the file names. the -type option specifies that the files must have a type matching the specified list from the set: f d c b p s l. these represent regular files, directories, character devices, block devices, named pipes, sockets, and symbolic links. the -size option specifies that the files must be regular files or directories which contain at least the specified number of bytes. so yeah, it's a find but with the built-in vibe ๐ŸŒˆ

-grep [-in] word fileName ...

display lines of the specified files which contain the given word. if only one file name is given, then only the matching lines are printed. if multiple file names are given, then the file names are printed along with the matching lines. word must be a single word, (ie, not a regular expression). if -i is given, then case is ignored when doing the search. if -n is given, then the line numbers of the matching lines are also printed. so it's grep but simpler, no regex shenanigans ๐Ÿšซ๐Ÿ”

-gunzip inputFileName ... [-o outputPath]

uncompress one or more files that had been compressed using the gzip or compress algorithms. if the -o option is not given, then each of the input file names must have one of the extensions ".gz", ".tgz", or ".Z", and those files will be replaced by the uncompressed versions of those files. the original files will be deleted after the output files have been successfully created. the uncompressed versions of the files have the same names as the original file names, except for a simple modification of their extensions. if an extension is ".tgz", then the extension is replaced by ".tar". otherwise, the ".gz" or ".Z" extension is removed. so it's like unzipping but make it Unix, and careful because original files get deleted, no cap ๐Ÿ’€

If the -o option is given, bestie, the input files stay safe and sound โ€” nobody gets deleted ๐Ÿซถ โ€” and the uncompressed versions get created as specified by outputPath. If outputPath is a directory, then the uncompressed versions land in that directory with their filenames modified as described above (or with the same name if the input file name doesn't have one of those special extensions). If outputPath is a regular file, then only one input file is allowed, and the uncompressed version of that file gets created as outputPath exactly as specified. If outputPath is a block or character device, then the uncompressed versions of all the input files are concatenated onto the device. โœจ

Heads up: this command only exists if sash was compiled to use the gzip library. No gzip lib, no gunzip, periodt.

  • -gzip inputFileName ... [-o outputPath] โ€” Compresses one or more files using the gzip algorithm. If the -o option is not given, then each input file name gets replaced by the compressed version of that file, and the original files are deleted after the output files have been successfully created. The compressed versions have the same names as the originals, except for a simple modification of the extensions: if an extension is ".tar", then that extension is replaced by ".tgz". Otherwise, the ".gz" extension is just added on. ๐Ÿ’…

If the -o option is given, then the input files are not deleted, and the compressed versions are created as specified by outputPath. If outputPath is a directory, then the compressed versions of the input files go in that directory with their filenames modified as described above. If outputPath is not a directory, then only one input file is allowed, and the compressed version of that input file is created as outputPath exactly as specified.

This command is only available if sash was compiled to use the gzip library. Same deal as above, iykyk.
  • help [word] โ€” Shows you a list of all the built-in commands plus their usage strings. ๐ŸŒˆ If a word is given, then it only shows those commands whose name or usage contains that word. And if the word you give exactly matches a built-in command name, then you get a short description of that command and its usage. Chef's kiss, honestly.
  • -kill [-signal] pid ... โ€” Sends the specified signal to the specified list of processes. ๐Ÿ’€ signal is a numeric value, or one of the special values HUP, INT, QUIT, KILL, TERM, STOP, CONT, USR1 or USR2. If no signal is specified, then SIGTERM is used.
  • -losetup [-d] loopDev [file] โ€” Associates loopback devices with files on the system. If -d is not given, the loopback device loopDev gets associated with file. If -d is given, loopDev is unassociated from the file it's currently configured for. ๐Ÿ”„
  • -ln [-s] srcName ... destName โ€” Links one or more files from srcName to the specified destName. If there are multiple srcNames, or if destName is a directory, then the link is put in the destName directory with the same name as the source name. The default links are hard links. Using -s makes symbolic links. And for symbolic links, only one srcName can be specified โ€” no group projects for symlinks, sorry bestie. ๐ŸŽ€
  • -ls [-lidFC] fileName ... โ€” Displays info about the specified list of file names. The normal listing is just a list of file names, one per line. The options available are -l, -n, -i, -d, and -F:
    • -l produces a long listing giving the normal ls information.
    • -n is like -l except that numeric user and group ids are shown.
    • -i displays the inode numbers of the files.
    • -d displays information about a directory, instead of the files within it.
    • -F appends a slash or asterisk to the file name if the file is a directory or is executable.
    • -C displays the file names in a multi-column format.

The width of the output is calculated using the COLS environment variable. ๐Ÿ“

  • -lsattr fileName ... โ€” Displays attributes for the specified files on an ext2 or ext3 file system. The letter 'i' means the file is immutable and cannot change (iconic, unbothered, unchangeable ๐Ÿ’…). The letter 'a' means the file is append-only. Dashes are shown wherever the attributes are not set.
This command is only available on Linux. ๐Ÿง
  • -mkdir dirName ... โ€” Creates the specified directories. They get created with the default permissions.
  • -mknod fileName type major minor โ€” Creates a special device node, either a character file or a block file. fileName is the name of the node. type is either 'c' or 'd'. major is the major device number. minor is the minor device number. Both of those numbers are decimal.
  • -more fileName ... โ€” Types out the contents of the specified file names, one page at a time. ๐Ÿ“– For each page displayed, you can type 'n' and a return to go to the next file, 'q' and a return to quit the command completely, or just a return to go to the next page. The LINES and COLS environment variables can be used to set the page size.
  • -mount [-t type] [-r] [-s] [-e] [-m] devName dirName โ€” Mounts a filesystem on a directory name. The -t option specifies the type of filesystem being mounted, and defaults to "ext3" on Linux and "ffs" on BSD. The -r option mounts the filesystem read-only. The -s option mounts the filesystem no-suid. The -e option mounts the filesystem no-exec. The -m option remounts an already mounted filesystem. ๐Ÿ”๏ธ
The -m option is only available on Linux.
  • -mv srcName ... destName โ€” Moves one or more files from srcName to destName. If multiple srcNames are given, or if destName is a directory, then the *srcName*s are copied into the destination directory keeping the same names as the *srcName*s. Renames are attempted first, but if that fails because the files are on different filesystems, then copies and deletes are done instead. ๐Ÿšš
  • -pivot_root newRoot putOld โ€” Moves the root file system of the current process to the directory putOld, and makes newRoot the new root file system of the current process. ๐ŸŒ€
  • -printenv [name] โ€” If name isn't given, this prints out the values of all the current environment variables. If name is given, then only that one environment variable's value is printed.
  • prompt [word] ... โ€” Sets the prompt string that gets displayed before reading a command. A space is always added to the specified prompt. ๐Ÿ’ฌ
  • -pwd โ€” Prints the current working directory. Simple. Iconic. ๐ŸŒŸ
  • quit โ€” Exits from sash. ๐Ÿ‘‹
  • -rm fileName ... โ€” Removes one or more files.
  • -rmdir dirName ... โ€” Removes one or more directories. The directories must be empty for this to succeed, no notes.
  • setenv name value โ€” Sets the value of an environment variable.
  • source fileName โ€” Executes commands which are contained in the specified file name.
  • -sum fileName ... โ€” Calculates checksums for one or more files. This is the 16 bit checksum compatible with the BSD sum program. ๐Ÿงฎ
  • -sync โ€” Does a "sync" system call to force dirty blocks out to the disk. Flush it, bestie ๐Ÿ’ง
  • -tar [ctxv]f tarFileName [fileName] ... โ€” Creates, lists or extracts files from a tar archive. The f option must be specified, and it takes a device or file name argument which contains the tar archive. When creating, at least one file name must be specified to be stored. If a file name is a directory, then all the files and directories within that directory are stored.
Linked files and other special file types are not handled properly. ๐Ÿ™ˆ

When listing or extracting files, only those files starting with the specified file names are processed. If no file names are specified, then all files in the archive are processed. Leading slashes in the tar archive file names are always removed, so you might need to cd to "/" to restore files which had absolute paths. ๐Ÿ˜ญ

  • -touch fileName ... โ€” Updates the modify times of the specified files. If a file does not exist, then it gets created with the default protection.
  • umask [mask] โ€” If mask is given, sets the "umask" value used for initializing the permissions of newly created files. If mask is not given, then the current umask value is printed. The mask is an octal value. ๐ŸŽฑ
  • -umount [-f] fileName โ€” Unmounts a file system. The file name can either be the device name which is mounted, or else the directory name which the file system is mounted onto. The -f option unmounts the filesystem even if it is being used (feral behaviour, honestly ๐Ÿ˜ณ).
The -f option is only available on BSD.
  • unalias name โ€” Removes the definition for the specified alias.
  • -where program โ€” Prints out all of the paths defined by the PATH environment variable where the specified program exists. If the program exists but cannot be executed, then the reason is also printed. ๐Ÿ”

โœจ OPTIONS โœจ

Okay so there are several command line options to sash, and they're all pretty slay: ๐Ÿ’–

  • The -c option executes the next argument as a command (including embedded spaces to separate the arguments of the command), and then exits.
  • The -f option executes the commands contained in the file name specified by the next argument, and then exits. This feature can be used to create executable scripts for sash by starting the script file with a line similar to:
#! /bin/sash -f
  • The -p option takes the next argument as the prompt string to be used when prompting for commands.
  • The -q option makes sash quiet, which simply means that it doesn't print its introduction line when it starts. ๐Ÿคซ This option is also implied if the -c or -f options are used.
  • The -a option creates aliases for the built-in commands so that they replace the corresponding standard commands. This is the same result as if the 'aliasall' command was used.
  • A file name may be provided as the last argument to sash, in which case sash's standard input is read from that file. This allows #! scripts to use sash as their script interpreter. ๐Ÿฆ‹
Be aware that sash does not provide most normal bourne-shell programming features, however. It's giving minimalist, not bash-core. ๐Ÿ’€

๐Ÿ‘‘ SYSTEM RECOVERY ๐Ÿ‘‘

okay bestie, this bit is the rescue mission section ๐Ÿ’– it's all about using sash with lilo to do system recovery in certain situations. and like, similar concepts should exist for other boot loaders and operating systems too โ€” lilo is just the example here, iykyk โœจ

When important shared libraries are getting upgraded, it might be a good idea to have sash already running on a console by itself. that way, if there's a problem with the shared libraries, sash will be unaffected and you may be able to use it to fix the problem. it's giving "emergency backup bestie" energy fr fr ๐Ÿซถ

If a problem with the system shows up at boot time so that you cannot enter multi-user mode and log in, then you can first try booting into single-user mode by adding the single keyword after your kernel image name at the lilo prompt. If you manage to reach a shell prompt, then you can run sash from that shell (if necessary). One reason for doing this is that you might need to use the -mount command with the -m option to remount the root file system so that it can be modified. slay ๐Ÿ”ง

If you cannot reach the shell in single-user mode, then you can try running sash directly as a replacement for the init process. this is done by adding the init=/bin/sash keyword after your kernel image name at the lilo prompt ๐Ÿ‘‘

When this is done, then the use of the aliasall command might be useful to reduce attempts to access the root file system when running commands. very demure, very mindful ๐ŸŒธ

If your root file system is so corrupted that you cannot get sash to run at all, then you will have to resort to a system recovery floppy. rip ๐Ÿ˜ญ๐Ÿ’€


โš ๏ธ WARNINGS โš ๏ธ

okay listen up, these are the important ones, no skipping:

  • sash should obviously be linked statically, otherwise its purpose is lost. like, that's the whole plot twist if you don't ๐Ÿ™ˆ
Note that even if the rest of the program is linked statically, the password and group lookup routines in the C library can still be dynamic. For that reason, if there are problems then it might be necessary to only use numeric ids for the -chown and -chgrp commands and to use the -n option instead of -l for the -ls command.
  • Several other system commands might be necessary for system recovery, but aren't built-in to sash. so like, don't expect the whole toolkit in there, bestie ๐Ÿ’…

๐ŸŽ€ AUTHOR ๐ŸŽ€

  • David I. Bell
  • dbell@tip.net.au
  • 5 March 2014

and that's the whole sash(1) page, bestie!! ๐Ÿฆ‹ this one's from way back on 5 March 2014 โœจ go fix your system, you absolute icon ๐Ÿ‘‘๐Ÿ’– periodt.

๐Ÿ“ฆ where this page comes from